Author: fanningpj
Date: Thu Jun 18 14:23:31 2026
New Revision: 1935475
Log:
fix out-of-bounds read in RANGE op of RegularExpression.match. Thanks to
aizu-m. This closes #58
Modified:
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/regex/RegularExpression.java
xmlbeans/trunk/src/test/java/misc/checkin/RegularExpressionTest.java
Modified:
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/regex/RegularExpression.java
==============================================================================
---
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/regex/RegularExpression.java
Thu Jun 18 13:18:53 2026 (r1935474)
+++
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/regex/RegularExpression.java
Thu Jun 18 14:23:31 2026 (r1935475)
@@ -647,7 +647,7 @@ public class RegularExpression implement
* @return true if the target is matched to this regular expression.
*/
public boolean matches(char[] target) {
- return this.matches(target, 0, target .length , (Match)null);
+ return this.matches(target, 0, target .length , null);
}
/**
@@ -659,7 +659,7 @@ public class RegularExpression implement
* @return true if the target is matched to this regular expression.
*/
public boolean matches(char[] target, int start, int end) {
- return this.matches(target, start, end, (Match)null);
+ return this.matches(target, start, end, null);
}
/**
@@ -833,7 +833,7 @@ public class RegularExpression implement
* @return true if the target is matched to this regular expression.
*/
public boolean matches(String target) {
- return this.matches(target, 0, target .length() , (Match)null);
+ return this.matches(target, 0, target .length() , null);
}
/**
@@ -845,7 +845,7 @@ public class RegularExpression implement
* @return true if the target is matched to this regular expression.
*/
public boolean matches(String target, int start, int end) {
- return this.matches(target, start, end, (Match)null);
+ return this.matches(target, start, end, null);
}
/**
@@ -1023,7 +1023,7 @@ public class RegularExpression implement
*/
private int match(Context con, Op op, int offset, int dx, int opts) {
final ExpressionTarget target = con.target;
- final Stack opStack = new Stack();
+ final Stack<Op> opStack = new Stack<>();
final IntStack dataStack = new IntStack();
final boolean isSetIgnoreCase = isSet(opts, IGNORE_CASE);
int retValue = -1;
@@ -1091,7 +1091,7 @@ public class RegularExpression implement
returned = true;
break;
}
- int ch = target.charAt(offset);
+ int ch = target.charAt(o1);
if (REUtil.isHighSurrogate(ch) && o1+dx < con.limit &&
o1+dx >=0) {
o1 += dx;
ch = REUtil.composeFromSurrogates(ch,
target.charAt(o1));
@@ -1304,7 +1304,7 @@ public class RegularExpression implement
return retValue;
}
- op = (Op) opStack.pop();
+ op = opStack.pop();
offset = dataStack.pop();
switch (op.type) {
@@ -1534,7 +1534,7 @@ public class RegularExpression implement
* @return true if the target is matched to this regular expression.
*/
public boolean matches(CharacterIterator target) {
- return this.matches(target, (Match)null);
+ return this.matches(target, null);
}
@@ -2401,8 +2401,7 @@ public class RegularExpression implement
if (ch <= '9') return true;
if (ch < 'A') return false;
if (ch <= 'Z') return true;
- if (ch < 'a') return false;
- return true;
+ return ch >= 'a';
}
private static boolean matchIgnoreCase(int chardata, int ch) {
Modified: xmlbeans/trunk/src/test/java/misc/checkin/RegularExpressionTest.java
==============================================================================
--- xmlbeans/trunk/src/test/java/misc/checkin/RegularExpressionTest.java
Thu Jun 18 13:18:53 2026 (r1935474)
+++ xmlbeans/trunk/src/test/java/misc/checkin/RegularExpressionTest.java
Thu Jun 18 14:23:31 2026 (r1935475)
@@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
import java.util.Random;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class RegularExpressionTest {
@@ -31,6 +32,18 @@ public class RegularExpressionTest {
assertTrue(regex.matches(rnd));
}
+ @Test
+ void testLookbehindRangeAtInputEnd() {
+ // a lookbehind containing a character class, evaluated at the end of
the
+ // input, used to read one character past the string in the RANGE op
and
+ // throw StringIndexOutOfBoundsException
+ assertTrue(new RegularExpression("(?<=[a-c])$").matches("abc"));
+ assertTrue(new RegularExpression(".*(?<=[0-9])").matches("ab9"));
+ // the same off-by-one read also returned the wrong match result: the
char
+ // before the lookbehind is 'x', not in [a-c], so this must not match
+ assertFalse(new RegularExpression("x(?<=[a-c])").matches("xc"));
+ }
+
private static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final Random rnd = new Random();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]