Fix for bug XMLBEANS-412. Contributed by Jerry Sy.
All checkin tests pass.
git-svn-id: https://svn.apache.org/repos/asf/xmlbeans/trunk@1330466 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/typeimpl/org/apache/xmlbeans/impl/regex/ParserForXMLSchema.java b/src/typeimpl/org/apache/xmlbeans/impl/regex/ParserForXMLSchema.java
index c040df2..ff41545 100644
--- a/src/typeimpl/org/apache/xmlbeans/impl/regex/ParserForXMLSchema.java
+++ b/src/typeimpl/org/apache/xmlbeans/impl/regex/ParserForXMLSchema.java
@@ -19,7 +19,7 @@
import java.util.Locale;
/**
- * A regular expression parser for the XML Shema.
+ * A regular expression parser for the XML Schema.
*
* @author TAMURA Kent <kent@trl.ibm.co.jp>
*/
@@ -159,7 +159,7 @@
* from-to-range ::= cc-normal-c '-' cc-normal-c
*
* @param useNrage Ignored.
- * @return This returns no NrageToken.
+ * @return This returns no NrangeToken.
*/
protected RangeToken parseCharacterClass(boolean useNrange) throws ParseException {
this.setContext(S_INBRACKETS);
@@ -234,9 +234,9 @@
if (type == T_CHAR) {
if (c == '[') throw this.ex("parser.cc.6", this.offset-2);
if (c == ']') throw this.ex("parser.cc.7", this.offset-2);
- // (radup) XMLSchema 1.0 allows the '-' as the first character of a range,
- // but it looks like XMLSchema 1.1 will prohibit it - track this
- if (c == '-' && !firstloop) throw this.ex("parser.cc.8", this.offset-2);
+ //https://issues.apache.org/jira/browse/XMLBEANS-412
+ //unescaped single char '-' is a valid char after '[' and before ']' positive range only
+ if (c== '-' && !firstloop && this.chardata!=']') throw this.ex("parser.cc.8", this.offset-2);
}
if (this.read() != T_CHAR || this.chardata != '-') { // Here is no '-'.
tok.addRange(c, c);
@@ -245,19 +245,27 @@
this.next(); // Skips '-'
if ((type = this.read()) == T_EOF) throw this.ex("parser.cc.2", this.offset);
// c '-' ']' -> '-' is a single-range.
- if ((type == T_CHAR && this.chardata == ']')
- || type == T_XMLSCHEMA_CC_SUBTRACTION) {
+ if (type == T_XMLSCHEMA_CC_SUBTRACTION) {
throw this.ex("parser.cc.8", this.offset-1);
+ } else if (type == T_CHAR && this.chardata == ']') {
+ //'-' occurs after a single-range but before ']'
+ tok.addRange(c,c);
+ tok.addRange('-','-');
} else {
int rangeend = this.chardata;
if (type == T_CHAR) {
if (rangeend == '[') throw this.ex("parser.cc.6", this.offset-1);
if (rangeend == ']') throw this.ex("parser.cc.7", this.offset-1);
- if (rangeend == '-') throw this.ex("parser.cc.8", this.offset-2);
+ if (rangeend == '-') {
+ this.next();
+ if (this.chardata!=']')
+ throw this.ex("parser.cc.8", this.offset-2);
+ }
}
else if (type == T_BACKSOLIDUS)
rangeend = this.decodeEscaped();
- this.next();
+ if (rangeend!='-' || this.chardata!=']')
+ this.next();
if (c > rangeend) throw this.ex("parser.ope.3", this.offset-1);
tok.addRange(c, rangeend);
diff --git a/test/src/misc/checkin/XMLBEANS412Test.java b/test/src/misc/checkin/XMLBEANS412Test.java
new file mode 100644
index 0000000..096b255
--- /dev/null
+++ b/test/src/misc/checkin/XMLBEANS412Test.java
@@ -0,0 +1,99 @@
+package misc.checkin;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.xmlbeans.impl.regex.ParseException;
+import org.apache.xmlbeans.impl.regex.RegularExpression;
+
+import java.util.StringTokenizer;
+
+public class XMLBEANS412Test extends TestCase
+{
+ static String PassedPosCharGroups = "-,\\-,--,\\--,---,\\---,--\\-,\\--\\-,-\\--,\\-\\--,-a,\\-a,a-,"+
+ "a\\-,a-b,a\\-b,a\\--,-a-z,\\-a-z,a-z-,a-z\\-,a-z\\-0-9,a\\-z-,a\\-z\\-,a\\-z\\-0-9,"+
+ "-0-9,0-9-,0-9aaa,0-9a-,a-z\\--/,A-F0-9.+-,-A-F0-9.+,A-F0-9.+\\-,\\-A-F0-9.+";
+
+ static String FailedPosCharGroups = "[a--],[a-z-0-9],[a\\-z-0-9],[0-9--],[0-9a--],[0-9-a],[0-9-a-z]";
+ static String MiscPassedPatterns = "([\\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(([a-zA-Z0-9_-])*\\.([a-zA-Z0-9_-])+)+";
+
+ public XMLBEANS412Test(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(XMLBEANS412Test.class);
+ }
+
+ public void testPassedPosCharGroupPatterns()
+ {
+ StringTokenizer tok = new StringTokenizer(PassedPosCharGroups,",");
+ while (tok.hasMoreElements()) {
+ String pattern = "[" + tok.nextToken() + "]";
+ try {
+ new RegularExpression(pattern, "X");
+ } catch (ParseException e) {
+ Assert.fail("Pattern " + pattern + " failed due to " + e.getMessage());
+ }
+ }
+ }
+
+ public void testNegatedPassedPosCharGroupPatterns()
+ {
+ StringTokenizer tok = new StringTokenizer(PassedPosCharGroups,",");
+ while (tok.hasMoreElements()) {
+ String pattern = "[^" + tok.nextToken() + "]";
+ try {
+ new RegularExpression(pattern, "X");
+ } catch (ParseException e) {
+ Assert.fail("Pattern " + pattern + " failed due to " + e.getMessage());
+ }
+ }
+
+
+ }
+
+ public void testFailedPosCharGroupPatterns()
+ {
+ StringTokenizer tok = new StringTokenizer(FailedPosCharGroups,",");
+ while (tok.hasMoreElements()) {
+ String pattern = "[" + tok.nextToken() + "]";
+ try {
+ new RegularExpression(pattern,"X");
+ } catch (ParseException e) {
+ continue;
+ }
+ Assert.fail("Pattern " + pattern + " did not fail.");
+ }
+ }
+
+ public void testNegatedFailedPosCharGroupPatterns()
+ {
+ StringTokenizer tok = new StringTokenizer(FailedPosCharGroups,",");
+ while (tok.hasMoreElements()) {
+ String pattern = "[^" + tok.nextToken() + "]";
+ try {
+ new RegularExpression(pattern,"X");
+ } catch (ParseException e) {
+ continue;
+ }
+ Assert.fail("Pattern " + pattern + " did not fail.");
+ }
+ }
+
+ public void testMiscPassedPatterns() {
+ StringTokenizer tok = new StringTokenizer(MiscPassedPatterns,",");
+ while (tok.hasMoreElements()) {
+ String pattern = tok.nextToken();
+ try {
+ new RegularExpression(pattern, "X");
+ } catch (ParseException e) {
+ Assert.fail("Pattern " + pattern + " failed due to " + e.getMessage());
+ }
+ }
+
+ }
+}