]> source.dussan.org Git - aspectj.git/commitdiff
406167: cope with rogue generic inner type signatures
authorAndy Clement <aclement@gopivotal.com>
Wed, 1 Apr 2015 15:02:01 +0000 (08:02 -0700)
committerAndy Clement <aclement@gopivotal.com>
Wed, 1 Apr 2015 15:02:01 +0000 (08:02 -0700)
util/src/org/aspectj/util/GenericSignatureParser.java
util/testsrc/org/aspectj/util/GenericSignatureParserTest.java

index 3f11662f6a2b969939e6aaac16f1205c8b3abbf6..28c8db83db209aaab111fef9152982c45c9a0f4e 100644 (file)
@@ -187,18 +187,10 @@ public class GenericSignatureParser {
                // now we have either a "." indicating the start of a nested type,
                // or a "<" indication type arguments, or ";" and we are done.
                while (!maybeEat(";")) {
-                       if (maybeEat(".")) {
+                       if (tokenStream[tokenIndex].equals(".")) {
                                // outer type completed
                                outerType = new SimpleClassTypeSignature(identifier);
-                               List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
-                               do {
-                                       ret.append(".");
-                                       SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
-                                       ret.append(sig.toString());
-                                       nestedTypeList.add(sig);
-                               } while (maybeEat("."));
-                               nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
-                               nestedTypeList.toArray(nestedTypes);
+                               nestedTypes = parseNestedTypesHelper(ret);
                        } else if (tokenStream[tokenIndex].equals("<")) {
                                ret.append("<");
                                TypeArgument[] tArgs = maybeParseTypeArguments();
@@ -207,16 +199,7 @@ public class GenericSignatureParser {
                                }
                                ret.append(">");
                                outerType = new SimpleClassTypeSignature(identifier, tArgs);
-                               // now parse possible nesteds...
-                               List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
-                               while (maybeEat(".")) {
-                                       ret.append(".");
-                                       SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
-                                       ret.append(sig.toString());
-                                       nestedTypeList.add(sig);
-                               }
-                               nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
-                               nestedTypeList.toArray(nestedTypes);
+                               nestedTypes = parseNestedTypesHelper(ret);
                        } else {
                                throw new IllegalStateException("Expecting .,<, or ;, but found " + tokenStream[tokenIndex] + " while unpacking "
                                                + inputString);
@@ -228,6 +211,39 @@ public class GenericSignatureParser {
                return new ClassTypeSignature(ret.toString(), outerType, nestedTypes);
        }
 
+       /**
+        * Helper method to digest nested types, slightly more complex than necessary to cope with some android related
+        * incorrect classes (see bug 406167)
+        */
+       private SimpleClassTypeSignature[] parseNestedTypesHelper(StringBuffer ret) {
+               boolean brokenSignature = false;
+               SimpleClassTypeSignature[] nestedTypes;
+               List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
+               while (maybeEat(".")) {
+                       ret.append(".");
+                       SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
+                       if (tokenStream[tokenIndex].equals("/")) {
+                               if (!brokenSignature) {
+                                       System.err.println("[See bug 406167] Bad class file signature encountered, nested types appear package qualified, ignoring those incorrect pieces. Signature: "+inputString);
+                               }
+                               brokenSignature = true;
+                               // hit something like: Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;
+                               // and we are looking at the '/' after the com
+                               tokenIndex++; // pointing at the next identifier
+                               while (tokenStream[tokenIndex+1].equals("/")) {
+                                       tokenIndex+=2; // jump over an 'identifier' '/' pair
+                               }
+                               // now tokenIndex is the final bit of the name (which we'll treat as the inner type name)
+                               sig = parseSimpleClassTypeSignature();
+                       }
+                       ret.append(sig.toString());
+                       nestedTypeList.add(sig);
+               };
+               nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
+               nestedTypeList.toArray(nestedTypes);
+               return nestedTypes;
+       }
+
        private SimpleClassTypeSignature parseSimpleClassTypeSignature() {
                String identifier = eatIdentifier();
                TypeArgument[] tArgs = maybeParseTypeArguments();
index c46c97b63c25ba03015721ba66e70fdc79acb800..5a9e083e404d3699d50497bbb1cf7c3ec7c99708 100644 (file)
@@ -95,6 +95,27 @@ public class GenericSignatureParserTest extends TestCase {
                assertEquals("Ljava/util/Comparable<-TE;>;", sig.superInterfaceSignatures[0].toString());
        }
 
+       public void testFunky_406167() {
+               ClassSignature sig = parser
+                               .parseAsClassSignature("Lcom/google/android/gms/internal/hb<TT;>.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
+               // Note the package prefix on the nested types has been dropped
+               assertEquals("Lcom/google/android/gms/internal/hb<TT;>.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
+               sig = parser
+                               .parseAsClassSignature("Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
+               // Note the package prefix on the nested types has been dropped
+               assertEquals("Lcom/a/a/b/t<TK;TV;>.af.ag;",sig.superclassSignature.toString());
+               assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
+               sig = parser.parseAsClassSignature("Lcom/google/android/gms/internal/hb.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
+               // Note the package prefix on the nested types has been dropped
+               assertEquals("Lcom/google/android/gms/internal/hb.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
+               sig = parser
+                               .parseAsClassSignature("Lcom/a/a/b/t.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
+               // Note the package prefix on the nested types has been dropped
+               assertEquals("Lcom/a/a/b/t.af.ag;",sig.superclassSignature.toString());
+               assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
+       }
+
+
        public void testFieldSignatureParsingClassType() {
                FieldTypeSignature fsig = parser.parseAsFieldSignature("Ljava/lang/String;");
                assertTrue("ClassTypeSignature", fsig instanceof ClassTypeSignature);
@@ -155,7 +176,7 @@ public class GenericSignatureParserTest extends TestCase {
                assertEquals("Ljava/lang/Exception;", mSig.throwsSignatures[0].toString());
                assertEquals("Ljava/lang/RuntimeException;", mSig.throwsSignatures[1].toString());
        }
-
+       
        public void testMethodSignaturePrimitiveParams() {
                GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("(ILjava/lang/Object;)V");
                assertEquals("2 parameters", 2, mSig.parameters.length);