Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassFormatException: Constant pool at index 0 is null #60

Closed
barney2k7 opened this issue Dec 5, 2016 · 10 comments
Closed

ClassFormatException: Constant pool at index 0 is null #60

barney2k7 opened this issue Dec 5, 2016 · 10 comments
Assignees

Comments

@barney2k7
Copy link

The problem described in findbugsproject/findbugs#141 also affects spotbugs, I just verified it with a current snapshot. The analysis of the following code fails:

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.stream.Stream;

public class MyClass {
  
  public static void create(URL url) {
    try (InputStream in = url.openStream()) {
      Properties p1 = new Properties();
      p1.load(in);
    } catch (IOException e) {
    }
  }
  
  public Stream<String> keys() {
    return Stream.<Properties>of().flatMap(p -> p.stringPropertyNames().stream());
  }

}

Stacktrace:

The following errors occurred during analysis:
  Exception analyzing MyClass using detector edu.umd.cs.findbugs.detect.FindUnsatisfiedObligation
    org.apache.bcel.classfile.ClassFormatException: Constant pool at index 0 is null.
      At org.apache.bcel.classfile.ConstantPool.getConstant(ConstantPool.java:258)
      At org.apache.bcel.classfile.ConstantPool.getConstantString(ConstantPool.java:293)
      At org.apache.bcel.generic.FieldOrMethod.getReferenceType(FieldOrMethod.java:116)
      At edu.umd.cs.findbugs.ba.obl.InstructionActionCache.getActions(InstructionActionCache.java:107)
      At edu.umd.cs.findbugs.ba.obl.ObligationAnalysis.transferInstruction(ObligationAnalysis.java:139)
      At edu.umd.cs.findbugs.ba.obl.ObligationAnalysis.transferInstruction(ObligationAnalysis.java:68)
      At edu.umd.cs.findbugs.ba.AbstractDataflowAnalysis.transfer(AbstractDataflowAnalysis.java:135)
      At edu.umd.cs.findbugs.ba.obl.ObligationAnalysis.transfer(ObligationAnalysis.java:160)
      At edu.umd.cs.findbugs.ba.obl.ObligationAnalysis.transfer(ObligationAnalysis.java:68)
      At edu.umd.cs.findbugs.ba.Dataflow.execute(Dataflow.java:376)
      At edu.umd.cs.findbugs.classfile.engine.bcel.ObligationDataflowFactory.analyze(ObligationDataflowFactory.java:75)
      At edu.umd.cs.findbugs.classfile.engine.bcel.ObligationDataflowFactory.analyze(ObligationDataflowFactory.java:45)
      At edu.umd.cs.findbugs.classfile.impl.AnalysisCache.analyzeMethod(AnalysisCache.java:369)
      At edu.umd.cs.findbugs.classfile.impl.AnalysisCache.getMethodAnalysis(AnalysisCache.java:322)
      At edu.umd.cs.findbugs.detect.FindUnsatisfiedObligation$MethodChecker.analyzeMethod(FindUnsatisfiedObligation.java:240)
      At edu.umd.cs.findbugs.detect.FindUnsatisfiedObligation.visitMethodCFG(FindUnsatisfiedObligation.java:158)
      At edu.umd.cs.findbugs.bcel.CFGDetector.visitClass(CFGDetector.java:93)
      At edu.umd.cs.findbugs.detect.FindUnsatisfiedObligation.visitClass(FindUnsatisfiedObligation.java:138)
      At edu.umd.cs.findbugs.FindBugs2.analyzeApplication(FindBugs2.java:1089)
      At edu.umd.cs.findbugs.FindBugs2.execute(FindBugs2.java:283)
      At edu.umd.cs.findbugs.gui2.BugLoader.doAnalysis(BugLoader.java:100)
      At edu.umd.cs.findbugs.gui2.AnalyzingDialog$AnalysisThread.run(AnalyzingDialog.java:274)

Thanks!

@KengoTODA
Copy link
Member

I will try to reproduce this in issue-20 branch.

@KengoTODA KengoTODA self-assigned this Dec 5, 2016
@KengoTODA KengoTODA added this to the SpotBugs 3.1.0 milestone Dec 5, 2016
@KengoTODA
Copy link
Member

I'm still testing #61, which is necessary to test your class with our integration test. Here is current patch:

diff --git a/findbugs/src/test/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligationTest.java b/findbugs/src/test/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligationTest.java
new file mode 100644
index 0000000..a767df9
--- /dev/null
+++ b/findbugs/src/test/java/edu/umd/cs/findbugs/detect/FindUnsatisfiedObligationTest.java
@@ -0,0 +1,22 @@
+package edu.umd.cs.findbugs.detect;
+
+import static org.junit.Assert.assertThat;
+
+import static org.hamcrest.core.Is.is;
+
+import static org.hamcrest.collection.IsEmptyIterable.*;
+import org.junit.Test;
+
+import edu.umd.cs.findbugs.AbstractIntegrationTest;
+
+public class FindUnsatisfiedObligationTest extends AbstractIntegrationTest {
+    /**
+     * @see <a href="https://github.com/spotbugs/spotbugs/issues/60">GitHub
+     *      issue</a>
+     */
+    @Test
+    public void testIssue60() {
+        performAnalysis("Issue60.class");
+        assertThat(getBugCollection(), is(emptyIterable()));
+    }
+}
diff --git a/findbugsTestCases/src/java/Issue60.java b/findbugsTestCases/src/java/Issue60.java
new file mode 100644
index 0000000..b79f1b8
--- /dev/null
+++ b/findbugsTestCases/src/java/Issue60.java
@@ -0,0 +1,22 @@
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+public class Issue60 {
+
+    public static void create(URL url) {
+        try (InputStream in = url.openStream()) {
+            Properties p1 = new Properties();
+            p1.load(in);
+        } catch (IOException e) {
+        }
+    }
+
+    public Stream<String> keys() {
+        return Stream.<Properties> of()
+                .flatMap(p -> p.stringPropertyNames().stream());
+    }
+
+}

@KengoTODA
Copy link
Member

By #69, I confirmed that current master branch has no problem. @barney2k7 please have a try.

@jsotuyod
Copy link
Member

jsotuyod commented Dec 7, 2016

@KengoTODA the exception does occur, but is managed and simply logged to stderr without the test failing.

@KengoTODA
Copy link
Member

KengoTODA commented Dec 7, 2016

@jsotuyod Oh... I also confirmed this behaviour. I will try to update AbstractIntegrationTest to mark our build as failed.

@jsotuyod
Copy link
Member

jsotuyod commented Dec 7, 2016

Running javap on the compiled source we can see the offending code:

  public java.util.stream.Stream<java.lang.String> keys();
    descriptor: ()Ljava/util/stream/Stream;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: iconst_0
         1: anewarray     #3                  // class java/util/Properties
         4: invokestatic  #10                 // InterfaceMethod java/util/stream/Stream.of:([Ljava/lang/Object;)Ljava/util/stream/Stream;
         7: invokedynamic #11,  0             // InvokeDynamic #0:apply:()Ljava/util/function/Function;

And in the constant pool we can see:

Constant pool:
    #1 = Methodref          #16.#46       // java/lang/Object."<init>":()V
    #2 = Methodref          #47.#48       // java/net/URL.openStream:()Ljava/io/InputStream;
    #3 = Class              #49           // java/util/Properties
    #4 = Methodref          #3.#46        // java/util/Properties."<init>":()V
    #5 = Methodref          #3.#50        // java/util/Properties.load:(Ljava/io/InputStream;)V
    #6 = Methodref          #51.#52       // java/io/InputStream.close:()V
    #7 = Class              #53           // java/lang/Throwable
    #8 = Methodref          #7.#54        // java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
    #9 = Class              #55           // java/io/IOException
   #10 = InterfaceMethodref #56.#57       // java/util/stream/Stream.of:([Ljava/lang/Object;)Ljava/util/stream/Stream;
   #11 = InvokeDynamic      #0:#63        // #0:apply:()Ljava/util/function/Function;

This happens because the invokedynamic is acting on the method handle, which of course, has no class name.

This is a bug on BCEL, that should override getReferenceType on INVOKEDYNAMIC to at least not throw a ClassFormatException. What do you think @mebigfatguy ?

In the meantime, we may rewrite the detector to handle INVOKEDYNAMIC separately.

@mebigfatguy
Copy link
Contributor

yeah, should add a bug here http://issues.apache.org/jira/browse/BCEL

@mebigfatguy
Copy link
Contributor

mebigfatguy commented Dec 7, 2016

i suppose it should return Object?or....? i'll add it.

https://issues.apache.org/jira/browse/BCEL-284

@jsotuyod
Copy link
Member

jsotuyod commented Dec 7, 2016

You are amazing! Thanks for the quick fix

I guess for the time being we can wait for a BCEL 6.1 release / use a snapshot until we reach the point of releasing Spotbugs 3.1.0

KengoTODA added a commit to KengoTODA/spotbugs that referenced this issue Dec 7, 2016
@KengoTODA KengoTODA mentioned this issue Dec 9, 2016
KengoTODA added a commit to KengoTODA/spotbugs that referenced this issue Dec 10, 2016
KengoTODA added a commit to KengoTODA/spotbugs that referenced this issue Dec 14, 2016
KengoTODA added a commit to KengoTODA/spotbugs that referenced this issue Dec 14, 2016
KengoTODA added a commit to KengoTODA/spotbugs that referenced this issue Jan 7, 2017
KengoTODA added a commit that referenced this issue Jan 22, 2017
* refs #60: reproduce reported problem

* refs #60: throw AssertionError when bugReporter has Error

* refs #60: confirm that BCEL 6.1 can solve this problem

* refs #60: use BCEL 6.1-SNAPSHOT

* refs #60: add missing dependency

* refs #60: include bcel 6.1 into built artifact
@KengoTODA
Copy link
Member

This problem should be solved by #69. I will close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants