Bug 4410: Loop in typedefs causes stack overflow 55/28555/11
authorPeter Kajsa <pkajsa@cisco.com>
Mon, 19 Oct 2015 13:22:42 +0000 (15:22 +0200)
committerPeter Kajsa <pkajsa@cisco.com>
Fri, 27 Nov 2015 08:59:56 +0000 (08:59 +0000)
The following kind of loop in the typedefs causes stack overflow error during the compilation of the yang file:

    typedef foo {
     type bar;
    }

    typedef bar {
     type foo;
    }

The compiler should provide descriptive error message instead.

Change-Id: Ia752a7de4a6e1ec1c7018fadc1428845d820e390
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/TypeStatementImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/retest/YangParserNegativeTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4410Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug4410/foo.yang [new file with mode: 0644]

index aed2fda2786192031f08d97831c3c2463f6bb124..251bbe2365d537af3b8d64d8c5f44788f9afd35a 100644 (file)
@@ -9,12 +9,20 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
 import java.util.Collection;
 import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
+import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ExtendedTypeEffectiveStatementImpl;
@@ -102,6 +110,43 @@ public class TypeStatementImpl extends AbstractDeclaredStatement<String>
                 return new ExtendedTypeEffectiveStatementImpl(ctx, false);
             }
         }
+
+        @Override
+        public void onFullDefinitionDeclared(
+                final Mutable<String, TypeStatement, EffectiveStatement<String, TypeStatement>> stmt)
+                throws SourceException {
+
+            // if it is yang built-in type, no prerequisite is needed, so simply return
+            if (TypeUtils.isYangBuiltInTypeString(stmt.getStatementArgument())) {
+                return;
+            }
+
+            final QName typeQName = Utils.qNameFromArgument(stmt, stmt.getStatementArgument());
+            final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
+            final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
+                    typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
+            typeAction.mutatesEffectiveCtx(stmt.getParentContext());
+
+            /*
+             * If the type does not exist, throw new InferenceException.
+             * Otherwise perform no operation.
+             */
+            typeAction.apply(new InferenceAction() {
+
+                @Override
+                public void apply() {
+                    // Intentional NOOP
+                }
+
+                @Override
+                public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed) {
+                    if (failed.contains(typePrereq)) {
+                        throw new InferenceException(String.format("Type [%s] was not found.", typeQName), stmt
+                                .getStatementSourceReference());
+                    }
+                }
+            });
+        }
     }
 
     @Nonnull
index 9d82d20d8f9ed63c4588a8e33abff2cb8d1e5e34..1b3c38badf2fd11d860fb04d77535042684e3cf6 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.yangtools.yang.stmt.retest;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+
+import com.google.common.base.Throwables;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
@@ -24,7 +26,6 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedEx
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
-import com.google.common.base.Throwables;
 
 public class YangParserNegativeTest {
 
@@ -50,11 +51,13 @@ public class YangParserNegativeTest {
         try {
             try (InputStream stream = new FileInputStream(yang)) {
                 TestUtils.loadModule(stream);
-                fail("IllegalArgumentException should be thrown");
+                fail("SomeModifiersUnresolvedException should be thrown.");
             }
-        } catch (IllegalStateException e) {
-            assertTrue(e.getMessage().startsWith(
-                    "Type '(urn:simple.types.data.demo?revision=2013-02-27)int-ext' was not found"));
+        } catch (SomeModifiersUnresolvedException e) {
+            Throwable rootCause = Throwables.getRootCause(e);
+            assertTrue(rootCause instanceof InferenceException);
+            assertTrue(rootCause.getMessage()
+                    .startsWith("Type [(urn:simple.types.data.demo?revision=2013-02-27)int-ext] was not found."));
         }
     }
 
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4410Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug4410Test.java
new file mode 100644 (file)
index 0000000..af22199
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  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.stmt.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Throwables;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+public class Bug4410Test {
+
+    @Test
+    public void test() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSources("/bugs/bug4410");
+            fail("SomeModifiersUnresolvedException should be thrown.");
+        } catch (SomeModifiersUnresolvedException e) {
+            Throwable rootCause = Throwables.getRootCause(e);
+            assertTrue(rootCause instanceof InferenceException);
+            final String message = rootCause.getMessage();
+            assertTrue(message.startsWith("Type [(foo?revision=1970-01-01)"));
+            assertTrue(message.endsWith("was not found."));
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug4410/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug4410/foo.yang
new file mode 100644 (file)
index 0000000..a733b46
--- /dev/null
@@ -0,0 +1,13 @@
+module foo {
+    namespace "foo";
+    prefix "foo";
+    yang-version 1;
+
+    typedef foo {
+        type bar;
+    }
+
+    typedef bar {
+        type foo;
+    }
+}