Force path expression parsing consume all data 47/86547/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 22 Dec 2019 10:20:29 +0000 (11:20 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 22 Dec 2019 13:12:29 +0000 (14:12 +0100)
We really need to make sure we do not end up ignoring part of the
expression just because our rules are not exhaustive. This adds
the appropriate test and fix in grammar.

JIRA: YANGTOOLS-1049
Change-Id: I85278f0cd109897459be1db029fafbc95e203201
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 8dc8c85e43be7c78a8aa4081d970e924b9757b3f)

yang/yang-data-impl/src/main/antlr/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefPathParser.g4
yang/yang-parser-rfc7950/src/main/antlr/org/opendaylight/yangtools/antlrv4/code/gen/LeafRefPathParser.g4
yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/path/PathExpressionParserTest.java [new file with mode: 0644]

index ec60a4cc32150afbbc40a00377ac2b2d3cb31145..1ae7f9ef6767130dcebc551a4e2556b850d41d43 100644 (file)
@@ -4,7 +4,7 @@ options {
     tokenVocab = LeafRefPathLexer;
 }
 
-path_arg : absolute_path | relative_path;
+path_arg : (absolute_path | relative_path) EOF;
 
 absolute_path : (SLASH node_identifier (path_predicate)*)+;
 
index ec60a4cc32150afbbc40a00377ac2b2d3cb31145..1ae7f9ef6767130dcebc551a4e2556b850d41d43 100644 (file)
@@ -4,7 +4,7 @@ options {
     tokenVocab = LeafRefPathLexer;
 }
 
-path_arg : absolute_path | relative_path;
+path_arg : (absolute_path | relative_path) EOF;
 
 absolute_path : (SLASH node_identifier (path_predicate)*)+;
 
diff --git a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/path/PathExpressionParserTest.java b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/path/PathExpressionParserTest.java
new file mode 100644 (file)
index 0000000..07ee8c3
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.path;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
+public class PathExpressionParserTest {
+    @Mock
+    private StmtContext<?, ?, ?> ctx;
+    @Mock
+    private StatementSourceReference ref;
+
+    @Before
+    public void before() {
+        doReturn(ref).when(ctx).getStatementSourceReference();
+    }
+
+    @Test
+    public void testDerefPath() {
+        try {
+            // deref() is not valid as per RFC7950, but YANGTOOLS-968 would allow it
+            new PathExpressionParser().parseExpression(ctx, "deref(../id)/../type");
+            fail("SourceException should have been thrown");
+        } catch (SourceException e) {
+            assertSame(ref, e.getSourceReference());
+            assertThat(e.getMessage(), startsWith("mismatched input '(' expecting "));
+            assertThat(e.getMessage(), containsString(" at 1:5 [at "));
+        }
+    }
+
+    @Test
+    public void testInvalidLeftParent() {
+        try {
+            new PathExpressionParser().parseExpression(ctx, "foo(");
+            fail("SourceException should have been thrown");
+        } catch (SourceException e) {
+            assertSame(ref, e.getSourceReference());
+            assertThat(e.getMessage(), startsWith("extraneous input '(' expecting "));
+            assertThat(e.getMessage(), containsString(" at 1:3 [at "));
+        }
+    }
+
+    @Test
+    public void testInvalidRightParent() {
+        try {
+            new PathExpressionParser().parseExpression(ctx, "foo)");
+            fail("SourceException should have been thrown");
+        } catch (SourceException e) {
+            assertSame(ref, e.getSourceReference());
+            assertThat(e.getMessage(), startsWith("extraneous input ')' expecting "));
+            assertThat(e.getMessage(), containsString(" at 1:3 [at "));
+        }
+    }
+
+    @Test
+    public void testInvalidIdentifier() {
+        try {
+            new PathExpressionParser().parseExpression(ctx, "foo%");
+            fail("SourceException should have been thrown");
+        } catch (SourceException e) {
+            assertSame(ref, e.getSourceReference());
+            assertThat(e.getMessage(), startsWith("token recognition error at: '%' at 1:3 [at "));
+        }
+    }
+}