Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8073313

Range error in javac LocalVariableTable AttributeReader

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Icon: P4 P4
    • None
    • 8u25
    • tools
    • x86
    • linux

      FULL PRODUCT VERSION :
      1.8.0_25 (not really applicable, see description)

      A DESCRIPTION OF THE PROBLEM :
      The problem is in share/classes/com/sun/tools/javac/jvm/ClassReader.java and has been present since at least JDK 1.6. In the latest hg version of langtools (langtools-1ff9d5118aae ), it's at lines 1049 - 1056:

      if (start_pc == 0) {
          // ensure array large enough
          if (register >= parameterNameIndices.length) {
              int newSize = Math.max(register, parameterNameIndices.length + 8);
              parameterNameIndices =
                      Arrays.copyOf(parameterNameIndices, newSize);
          }
          parameterNameIndices[register] = nameIndex;
          haveParameterNameIndices = true;
      }

      The problem is that if register >= parameterNameIndices.length + 8, then parameterNameIndices will be reallocated to an array of length "register", and next nameIndex will be written at index "register" of that array (which is 1 past the length of the array). Therefore, "newSize" should be assigned the result of Math.max(register+1, ...) instead.

      This situation (almost?) never happens with bytecode generated by javac itself, but it did happen with bytecode generated by our own compiler because we were not aware of this implicit assumption that all local variable declarations associated with bytecode 0 are assumed to be parameters (and hence we also put all of our local variables at that point, in some cases with the first one listed being more than 8 slots higher up the stack than the last parameter slot estimated by javac).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I can only provide you with either a class file or Jasmin input to construct a class file with such a LocalVariableTable. Let me know if this would be useful to you.

      The issue can then be triggered by using that class file in a NetBeans project and attempting to perform code completion (because that will trigger the attributes reader).

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Code completion works.
      ACTUAL -
      You get an exception.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      The following backtrace comes from a customer. I don't know which jdk version they use exactly, but I think it's a jdk 1.7 on Windows (I don't have NetBeans installed myself):

      Caused: java.lang.ArrayIndexOutOfBoundsException: 31
              at com.sun.tools.javac.jvm.ClassReader$7.read(ClassReader.java:1022)
              at com.sun.tools.javac.jvm.ClassReader.readAttrs(ClassReader.java:1338)
              at com.sun.tools.javac.jvm.ClassReader.readMemberAttrs(ClassReader.java:1328)
              at com.sun.tools.javac.jvm.ClassReader.readCode(ClassReader.java:1365)
              at com.sun.tools.javac.jvm.ClassReader$2.read(ClassReader.java:956)
              at com.sun.tools.javac.jvm.ClassReader.readAttrs(ClassReader.java:1338)
              at com.sun.tools.javac.jvm.ClassReader.readMemberAttrs(ClassReader.java:1328)
              at com.sun.tools.javac.jvm.ClassReader.readMethod(ClassReader.java:1812)
              at com.sun.tools.javac.jvm.ClassReader.readClass(ClassReader.java:2012)
              at com.sun.tools.javac.jvm.ClassReader.readClassFile(ClassReader.java:2084)
              at com.sun.tools.javac.jvm.ClassReader.fillIn(ClassReader.java:2306)
              at com.sun.tools.javac.jvm.ClassReader.complete(ClassReader.java:2226)
              at com.sun.tools.javac.code.Symbol.complete(Symbol.java:422)
              at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:833)
              at com.sun.tools.javac.jvm.ClassReader.loadClass(ClassReader.java:2420)
              at com.sun.tools.javac.comp.Resolve.loadClass(Resolve.java:1065)
              at com.sun.tools.javac.comp.Resolve.findIdentInPackage(Resolve.java:1237)
              at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:2471)
              at com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:2362)
              at com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:1680)
              at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:451)
              at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:424)
              at com.sun.tools.javac.comp.Attr.attribType(Attr.java:494)
              at com.sun.tools.javac.comp.Attr.attribType(Attr.java:487)
              at com.sun.tools.javac.comp.MemberEnter.attribImportType(MemberEnter.java:919)
              at com.sun.tools.javac.comp.MemberEnter.visitImport(MemberEnter.java:584)
              at org.netbeans.lib.nbjavac.services.NBJavadocMemberEnter.visitImport(NBJavadocMemberEnter.java:78)
              at com.sun.tools.javac.tree.JCTree$JCImport.accept(JCTree.java:511)
              at com.sun.tools.javac.comp.MemberEnter.memberEnter(MemberEnter.java:421)
              at com.sun.tools.javac.comp.MemberEnter.memberEnter(MemberEnter.java:433)
              at com.sun.tools.javac.comp.MemberEnter.visitTopLevel(MemberEnter.java:551)
              at org.netbeans.lib.nbjavac.services.NBJavadocMemberEnter.visitTopLevel(NBJavadocMemberEnter.java:72)
              at com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:457)
              at com.sun.tools.javac.comp.MemberEnter.memberEnter(MemberEnter.java:421)
              at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:1075)
              at com.sun.tools.javac.code.Symbol.complete(Symbol.java:422)
              at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:833)
              at com.sun.tools.javac.comp.Enter.complete(Enter.java:715)
              at com.sun.tools.javac.main.JavaCompiler.complete(JavaCompiler.java:979)
              at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:945)
              at com.sun.tools.javac.api.JavacTaskImpl.enter(JavacTaskImpl.java:369)
              at com.sun.tools.javac.api.JavacTaskImpl.enter(JavacTaskImpl.java:315)
              at org.netbeans.modules.java.source.parsing.JavacParser.moveToPhase(JavacParser.java:648)
              at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:516)
              at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:169)
              at org.netbeans.modules.parsing.impl.TaskProcessor.callGetResult(TaskProcessor.java:606)
              at org.netbeans.modules.parsing.impl.SourceCache.getResult(SourceCache.java:247)
      [catch] at org.netbeans.modules.parsing.impl.TaskProcessor$CompilationJob.run(TaskProcessor.java:718)
              at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
              at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
              at java.util.concurrent.FutureTask.run(FutureTask.java:138)
              at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
              at java.lang.Thread.run(Thread.java:662)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      As mentioned above, I can't give you Java source code, only Jasmin input (as generated by our compiler) that will assemble into a class file. Let me know if you want this, or a class file itself.
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I have modified our compiler to no longer associate the debug information for local variables with bytecode offset 0 of a method.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: