You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2025/02/13 11:39:41 UTC
(lucene) branch branch_10x updated: Fix failure found by TestOperations.testGetRandomAcceptedString (#14227)
This is an automated email from the ASF dual-hosted git repository.
rmuir pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new 7682ef096e2 Fix failure found by TestOperations.testGetRandomAcceptedString (#14227)
7682ef096e2 is described below
commit 7682ef096e269354b0f24152ae60dace152b866b
Author: Robert Muir <rm...@apache.org>
AuthorDate: Thu Feb 13 06:22:25 2025 -0500
Fix failure found by TestOperations.testGetRandomAcceptedString (#14227)
* Fix failure found by TestOperations.testGetRandomAcceptedString
string: ?+½]+]+Ř*+[\]ᖴﴁ.
expected: before #14193
java.lang.IllegalArgumentException: expected ']' at position 17
actual: after #14193
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_CONCATENATION
REGEXP_REPEAT_MIN min=1
REGEXP_CHAR char=?
REGEXP_CHAR char=½
REGEXP_REPEAT_MIN min=1
REGEXP_CHAR char=]
REGEXP_CHAR char=
REGEXP_REPEAT_MIN min=1
REGEXP_CHAR char=]
REGEXP_REPEAT_MIN min=1
REGEXP_REPEAT
REGEXP_CHAR char=Ř
REGEXP_CHAR_CLASS starts=[] ends=[]
REGEXP_STRING string=ᖴﴁ
REGEXP_ANYCHAR
Problem is caused by RegExp accepting too much rather than throwing
exceptions like it should have. The lenience in the parser comes from
"expandPreDefined" which invades on escape character parsing for character
classes (e.g. \s). This one adds a lot of complexity to parsing.
Don't invoke expandPreDefined(), except for the set of characters that it
explicitly handles. This is also consistent with the way
expandPreDefined()'s complexity is managed elsewhere in the parser, such
as in parseSimpleExp().
Add parsing tests for testEmptyClass(), which is unchanged by this PR,
but should be there, and testEscapedInvalidClass(), which fails without
the change.
When we consume an escape, either it matches the predefined special
logic, or we emit range for next(), no other logic: it is an escape.
Add test for escaped '-' in a character class.
---
.../org/apache/lucene/util/automaton/RegExp.java | 10 +++++++-
.../lucene/util/automaton/TestOperations.java | 5 ++--
.../lucene/util/automaton/TestRegExpParsing.java | 29 ++++++++++++++++++++++
3 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/lucene/core/src/java/org/apache/lucene/util/automaton/RegExp.java b/lucene/core/src/java/org/apache/lucene/util/automaton/RegExp.java
index aaf50c8c180..8be1a0eb12c 100644
--- a/lucene/core/src/java/org/apache/lucene/util/automaton/RegExp.java
+++ b/lucene/core/src/java/org/apache/lucene/util/automaton/RegExp.java
@@ -1243,7 +1243,15 @@ public class RegExp {
do {
// look for escape
if (match('\\')) {
- expandPreDefined(starts, ends);
+ if (peek("\\ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) {
+ // special "escape" or invalid escape
+ expandPreDefined(starts, ends);
+ } else {
+ // escaped character, don't parse it
+ int c = next();
+ starts.add(c);
+ ends.add(c);
+ }
} else {
// parse a character
int c = parseCharExp();
diff --git a/lucene/core/src/test/org/apache/lucene/util/automaton/TestOperations.java b/lucene/core/src/test/org/apache/lucene/util/automaton/TestOperations.java
index 7fb1d679946..aedac499ecc 100644
--- a/lucene/core/src/test/org/apache/lucene/util/automaton/TestOperations.java
+++ b/lucene/core/src/test/org/apache/lucene/util/automaton/TestOperations.java
@@ -132,10 +132,11 @@ public class TestOperations extends LuceneTestCase {
final int ITER2 = atLeast(100);
for (int i = 0; i < ITER1; i++) {
- final RegExp re = new RegExp(AutomatonTestUtil.randomRegexp(random()), RegExp.NONE);
+ final String text = AutomatonTestUtil.randomRegexp(random());
+ final RegExp re = new RegExp(text, RegExp.NONE);
// System.out.println("TEST i=" + i + " re=" + re);
final Automaton a = Operations.determinize(re.toAutomaton(), DEFAULT_DETERMINIZE_WORK_LIMIT);
- assertFalse(Operations.isEmpty(a));
+ assertFalse("empty: " + text, Operations.isEmpty(a));
final AutomatonTestUtil.RandomAcceptedStrings rx =
new AutomatonTestUtil.RandomAcceptedStrings(a);
diff --git a/lucene/core/src/test/org/apache/lucene/util/automaton/TestRegExpParsing.java b/lucene/core/src/test/org/apache/lucene/util/automaton/TestRegExpParsing.java
index 51a14761d38..c5e269b51f9 100644
--- a/lucene/core/src/test/org/apache/lucene/util/automaton/TestRegExpParsing.java
+++ b/lucene/core/src/test/org/apache/lucene/util/automaton/TestRegExpParsing.java
@@ -379,6 +379,15 @@ public class TestRegExpParsing extends LuceneTestCase {
assertSameLanguage(expected, actual);
}
+ public void testEscapedDashCharClass() {
+ RegExp re = new RegExp("[\\-]");
+ assertEquals("REGEXP_CHAR char=-\n", re.toStringTree());
+ Automaton actual = re.toAutomaton();
+ assertTrue(actual.isDeterministic());
+ Automaton expected = Automata.makeChar('-');
+ assertSameLanguage(expected, actual);
+ }
+
public void testEmpty() {
RegExp re = new RegExp("#", RegExp.EMPTY);
assertEquals("#", re.toString());
@@ -391,6 +400,26 @@ public class TestRegExpParsing extends LuceneTestCase {
assertSameLanguage(expected, actual);
}
+ public void testEmptyClass() {
+ Exception expected =
+ expectThrows(
+ IllegalArgumentException.class,
+ () -> {
+ new RegExp("[]");
+ });
+ assertEquals("expected ']' at position 2", expected.getMessage());
+ }
+
+ public void testEscapedInvalidClass() {
+ Exception expected =
+ expectThrows(
+ IllegalArgumentException.class,
+ () -> {
+ new RegExp("[\\]");
+ });
+ assertEquals("expected ']' at position 3", expected.getMessage());
+ }
+
public void testInterval() {
RegExp re = new RegExp("<5-40>");
assertEquals("<5-40>", re.toString());