This is an automated email from the ASF dual-hosted git repository.
opwvhk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/main by this push:
new 34bdcf98ab AVRO-4182: Avoid ANTLR parsing edge cases (#3756)
34bdcf98ab is described below
commit 34bdcf98ab5d0639219f4d1ec144828e0bfa58fe
Author: Oscar Westra van Holthe - Kind <[email protected]>
AuthorDate: Fri May 15 18:55:10 2026 +0200
AVRO-4182: Avoid ANTLR parsing edge cases (#3756)
In some cases, enter and exit rules are not called in pairs while parsing.
Apparently, this is by design. This fix adds a test that the fix does indeed
work (it tests an exception, as the error does not show up with a duplicated
definition).
Note: this change keeps the entire parse tree in memory during parsing,
and allows it to be collected directly afterwards.
---
.../idl/src/main/java/org/apache/avro/idl/IdlReader.java | 14 ++++++++------
.../idl/src/test/idl/extra/duplicateNameErrorParsing.avdl | 14 ++++++++++++++
.../src/test/java/org/apache/avro/idl/TestIdlReader.java | 12 +++++++++++-
3 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/lang/java/idl/src/main/java/org/apache/avro/idl/IdlReader.java
b/lang/java/idl/src/main/java/org/apache/avro/idl/IdlReader.java
index f6d1fb49dc..85c7d5a568 100644
--- a/lang/java/idl/src/main/java/org/apache/avro/idl/IdlReader.java
+++ b/lang/java/idl/src/main/java/org/apache/avro/idl/IdlReader.java
@@ -34,6 +34,7 @@ import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.apache.avro.JsonProperties;
import org.apache.avro.JsonSchemaParser;
import org.apache.avro.LogicalType;
@@ -207,20 +208,21 @@ public class IdlReader {
IdlParser parser = new IdlParser(tokenStream);
parser.removeErrorListeners();
parser.addErrorListener(SIMPLE_AVRO_ERROR_LISTENER);
- parser.addParseListener(parseListener);
parser.setTrace(false);
- parser.setBuildParseTree(false);
+ // Parse the input, then walk the parse tree using the listener.
+ // Although the parse can call the listener directly, there are edge cases
where
+ // the enter and exit rules are not called in pairs. This a known issue and
+ // currently by design. See: https://github.com/antlr/antlr4/issues/18
try {
- // Trigger parsing.
- parser.idlFile();
+ IdlFileContext idlFileContext = parser.idlFile();
+ ParseTreeWalker.DEFAULT.walk(parseListener, idlFileContext);
+ return parseListener.getIdlFile();
} catch (SchemaParseException e) {
throw e;
} catch (RuntimeException e) {
throw new SchemaParseException(e);
}
-
- return parseListener.getIdlFile();
}
/* Package private to facilitate testing */
diff --git a/lang/java/idl/src/test/idl/extra/duplicateNameErrorParsing.avdl
b/lang/java/idl/src/test/idl/extra/duplicateNameErrorParsing.avdl
new file mode 100644
index 0000000000..f6700b0d77
--- /dev/null
+++ b/lang/java/idl/src/test/idl/extra/duplicateNameErrorParsing.avdl
@@ -0,0 +1,14 @@
+namespace duplicateNameParseError;
+
+// Test that parsing fails when redefining an enum with different symbols.
+// Avro 1.12.0 fails to parse this, but the correct result is an explicit
error that redefinition is not allowed.
+
+enum Foo {
+ UNKNOWN,
+ BAR
+} = UNKNOWN;
+
+enum Foo {
+ UNKNOWN,
+ BAZ
+} = UNKNOWN;
diff --git a/lang/java/idl/src/test/java/org/apache/avro/idl/TestIdlReader.java
b/lang/java/idl/src/test/java/org/apache/avro/idl/TestIdlReader.java
index 96034cf395..d437f9299b 100644
--- a/lang/java/idl/src/test/java/org/apache/avro/idl/TestIdlReader.java
+++ b/lang/java/idl/src/test/java/org/apache/avro/idl/TestIdlReader.java
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.avro.Protocol;
import org.apache.avro.Schema;
+import org.apache.avro.SchemaParseException;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedReader;
@@ -156,7 +157,16 @@ public class TestIdlReader {
warnings);
}
- @SuppressWarnings("SameParameterValue")
+ @Test
+ public void testErrorDuplicateNamedType() throws IOException {
+ try {
+ parseExtraIdlFile("duplicateNameErrorParsing.avdl");
+ fail("Expected a failure: named schemas cannot be redefined.");
+ } catch (SchemaParseException e) {
+ assertEquals("Can't redefine: duplicateNameParseError.Foo",
e.getMessage());
+ }
+ }
+
private IdlFile parseExtraIdlFile(String fileName) throws IOException {
return new IdlReader().parse(EXTRA_TEST_DIR.toPath().resolve(fileName));
}