Infinite recursion in ClassFile.foreachNestedClasses

Issue #45 resolved
Daniel Klauer created an issue

FindRealBugs currently crashes when analyzing most projects of the Qualitas Corpus, due to infinite recursion in ClassFile.foreachNestedClasses.

I have attached an example set of class files from the ant project. Corresponding source code: http://grepcode.com/file/repo1.maven.org/maven2/org.apache.ant/ant/1.8.4/org/apache/tools/ant/util/ResourceUtils.java#ResourceUtils

Output of ShowInnerClassesAttribute from OPAL's Demos project:

org/apache/tools/ant/util/ResourceUtils:
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$ResourceSelectorProvider,outerType=Some(org.apache.tools.ant.util.ResourceUtils),innerName=Some(ResourceSelectorProvider),accessFlags="public static [INTERFACE] abstract")
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$1,outerType=None,innerName=None,accessFlags="static")
org/apache/tools/ant/util/ResourceUtils$1:
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$1,outerType=None,innerName=None,accessFlags="static")
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$2,outerType=None,innerName=None,accessFlags="")
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$ResourceSelectorProvider,outerType=Some(org.apache.tools.ant.util.ResourceUtils),innerName=Some(ResourceSelectorProvider),accessFlags="public static [INTERFACE] abstract")
org/apache/tools/ant/util/ResourceUtils$2:
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$1,outerType=None,innerName=None,accessFlags="static")
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$2,outerType=None,innerName=None,accessFlags="")
org/apache/tools/ant/util/ResourceUtils$ResourceSelectorProvider:
    InnerClass(type=org.apache.tools.ant.util.ResourceUtils$ResourceSelectorProvider,outerType=Some(org.apache.tools.ant.util.ResourceUtils),innerName=Some(ResourceSelectorProvider),accessFlags="public static [INTERFACE] abstract")

Simplified:

ResourceUtils:
    ResourceUtils$ResourceSelectorProvider
    ResourceUtils$1
ResourceUtils$1:
    ResourceUtils$1
    ResourceUtils$2
    ResourceUtils$ResourceSelectorProvider
ResourceUtils$2:
    ResourceUtils$1
    ResourceUtils$2
ResourceUtils$ResourceSelectorProvider:
    ResourceUtils$ResourceSelectorProvider

The problem seems to be that the two inner classes ResourceUtils$1 and ResourceUtils$2 are referencing each other in their inner classes attributes. After looking at the source code, apparently they were produced by a construct such as:

class Test {
    Foo returnFoo() {
        return new Foo() {
            Bar returnBar() {
                return new Bar() {
                }
            }
        }
    }
}

I could not reproduce that in a test case though, because it will produce Test$1 and Test$1$1 as opposed to Test$1 and Test$2 like in the attached class files. (Perhaps they were produced by an older Java compiler which behaved differently.)

Comments (20)

  1. Michael Eichberg repo owner

    After a very careful study it is obvious that this code violates the specification. (The class ResourceUtils$1 does not specify its outer class (it has no EnclosingMethod attribute)).

    However, given that multiple projects fail, I'll look for a solution!

  2. Michael Eichberg repo owner

    I implemented an approach that solves this (instance of?) problem. It will be available with the next commit.

    Anyway, I would highly appreciate it, if you could tell me if also works for the other projects in the qualitas corpus.

  3. Daniel Klauer reporter
    • changed status to open

    The issue has been solved for a lot of the projects from the Qualitas Corpus, but not all. I'll attach a set of class files from the batik 1.7 project which still trigger the infinite recursion problem.

  4. Daniel Klauer reporter

    Since the last change, there sometimes seems to be an infinite loop during foreachNestedClasses (although, no crash). I'll attach an affected set of class files.

  5. Michael Eichberg repo owner

    I wonder, if this issue will ever be finally resolved...

    (in this case the problem was a named inner class of an anonymous outer class, where the anonymous outer class did not give any information about the named inner class....)

  6. Log in to comment