aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/changes/changes.xml1
-rw-r--r--src/main/java/org/apache/bcel/classfile/Utility.java75
-rw-r--r--src/test/java/org/apache/bcel/classfile/UtilityTestCase.java13
3 files changed, 69 insertions, 20 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f270dcc0..83a34f44 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -63,6 +63,7 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<release version="6.1" date="tba" description="tba">
+ <action issue="BCEL-286" type="fix" dev="britter" due-to="Mark Roberts">Utility.signatureToString fails if a method has multiple type arguments</action>
<action issue="BCEL-287" type="fix" dev="britter" due-to="Mark Roberts">IINC does not handle -128 properly</action>
<action issue="BCEL-283" type="fix" dev="britter" due-to="Mark Roberts">Support for StackMap should be different from StackMapTable</action>
<action issue="BCEL-289" type="fix" dev="kinow">Crash when parsing constructor of inner classes with parameters annotated</action>
diff --git a/src/main/java/org/apache/bcel/classfile/Utility.java b/src/main/java/org/apache/bcel/classfile/Utility.java
index 5ec58680..12fca065 100644
--- a/src/main/java/org/apache/bcel/classfile/Utility.java
+++ b/src/main/java/org/apache/bcel/classfile/Utility.java
@@ -849,6 +849,7 @@ public abstract class Utility {
if (index < 0) {
throw new ClassFormatException("Invalid signature: " + signature);
}
+
// check to see if there are any TypeArguments
final int bracketIndex = signature.substring(0, index).indexOf('<');
if (bracketIndex < 0) {
@@ -856,6 +857,16 @@ public abstract class Utility {
wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed
return compactClassName(signature.substring(1, index), chopit);
}
+ // but make sure we are not looking past the end of the current item
+ fromIndex = signature.indexOf(';');
+ if (fromIndex < 0) {
+ throw new ClassFormatException("Invalid signature: " + signature);
+ }
+ if (fromIndex < bracketIndex) {
+ // just a class identifier
+ wrap(consumed_chars, fromIndex + 1); // "Lblabla;" `L' and `;' are removed
+ return compactClassName(signature.substring(1, fromIndex), chopit);
+ }
// we have TypeArguments; build up partial result
// as we recurse for each TypeArgument
@@ -869,37 +880,63 @@ public abstract class Utility {
} else if (signature.charAt(consumed_chars) == '-') {
type.append("? super ");
consumed_chars++;
- } else if (signature.charAt(consumed_chars) == '*') {
- // must be at end of signature
- if (signature.charAt(consumed_chars + 1) != '>') {
- throw new ClassFormatException("Invalid signature: " + signature);
- }
- if (signature.charAt(consumed_chars + 2) != ';') {
- throw new ClassFormatException("Invalid signature: " + signature);
- }
- wrap(Utility.consumed_chars, consumed_chars + 3); // remove final "*>;"
- return type + "?>...";
}
// get the first TypeArgument
- type.append(signatureToString(signature.substring(consumed_chars), chopit));
- // update our consumed count by the number of characters the for type argument
- consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars;
- wrap(Utility.consumed_chars, consumed_chars);
+ if (signature.charAt(consumed_chars) == '*') {
+ type.append("?");
+ consumed_chars++;
+ } else {
+ type.append(signatureToString(signature.substring(consumed_chars), chopit));
+ // update our consumed count by the number of characters the for type argument
+ consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars;
+ wrap(Utility.consumed_chars, consumed_chars);
+ }
// are there more TypeArguments?
while (signature.charAt(consumed_chars) != '>') {
- type.append(", ").append(signatureToString(signature.substring(consumed_chars), chopit));
+ type.append(", ");
+ // check for wildcards
+ if (signature.charAt(consumed_chars) == '+') {
+ type.append("? extends ");
+ consumed_chars++;
+ } else if (signature.charAt(consumed_chars) == '-') {
+ type.append("? super ");
+ consumed_chars++;
+ }
+ if (signature.charAt(consumed_chars) == '*') {
+ type.append("?");
+ consumed_chars++;
+ } else {
+ type.append(signatureToString(signature.substring(consumed_chars), chopit));
+ // update our consumed count by the number of characters the for type argument
+ consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars;
+ wrap(Utility.consumed_chars, consumed_chars);
+ }
+ }
+
+ // process the closing ">"
+ consumed_chars++;
+ type.append(">");
+
+ if (signature.charAt(consumed_chars) == '.') {
+ // we have a ClassTypeSignatureSuffix
+ type.append(".");
+ // convert SimpleClassTypeSignature to fake ClassTypeSignature
+ // and then recurse to parse it
+ type.append(signatureToString("L" + signature.substring(consumed_chars+1), chopit));
// update our consumed count by the number of characters the for type argument
+ // note that this count includes the "L" we added, but that is ok
+ // as it accounts for the "." we didn't consume
consumed_chars = unwrap(Utility.consumed_chars) + consumed_chars;
wrap(Utility.consumed_chars, consumed_chars);
+ return type.toString();
}
-
- if (signature.charAt(consumed_chars + 1) != ';') {
+ if (signature.charAt(consumed_chars) != ';') {
throw new ClassFormatException("Invalid signature: " + signature);
}
- wrap(Utility.consumed_chars, consumed_chars + 2); // remove final ">;"
- return type.append(">").toString();
+ wrap(Utility.consumed_chars, consumed_chars + 1); // remove final ";"
+ return type.toString();
}
case 'S':
return "short";
diff --git a/src/test/java/org/apache/bcel/classfile/UtilityTestCase.java b/src/test/java/org/apache/bcel/classfile/UtilityTestCase.java
index 36fa3272..80586570 100644
--- a/src/test/java/org/apache/bcel/classfile/UtilityTestCase.java
+++ b/src/test/java/org/apache/bcel/classfile/UtilityTestCase.java
@@ -22,6 +22,7 @@ import junit.framework.TestCase;
public class UtilityTestCase extends TestCase {
public void testSignatureToStringWithGenerics() throws Exception {
+ // tests for BCEL-197
assertEquals("generic signature",
"java.util.Map<X, java.util.List<Y>>",
Utility.signatureToString("Ljava/util/Map<TX;Ljava/util/List<TY;>;>;"));
@@ -29,7 +30,17 @@ public class UtilityTestCase extends TestCase {
"java.util.Set<? extends java.nio.file.OpenOption>"
, Utility.signatureToString("Ljava/util/Set<+Ljava/nio/file/OpenOption;>;"));
assertEquals("generic signature",
- "java.nio.file.attribute.FileAttribute<?>...[]",
+ "java.nio.file.attribute.FileAttribute<?>[]",
Utility.signatureToString("[Ljava/nio/file/attribute/FileAttribute<*>;"));
+ // tests for BCEL-286
+ assertEquals("generic signature",
+ "boofcv.alg.tracker.tld.TldTracker<boofcv.struct.image.ImageGray<boofcv.struct.image.GrayU8>, boofcv.struct.image.GrayI<boofcv.struct.image.GrayU8>>",
+ Utility.signatureToString("Lboofcv/alg/tracker/tld/TldTracker<Lboofcv/struct/image/ImageGray<Lboofcv/struct/image/GrayU8;>;Lboofcv/struct/image/GrayI<Lboofcv/struct/image/GrayU8;>;>;"));
+ assertEquals("generic signature",
+ "java.util.Map<?, ?>",
+ Utility.signatureToString("Ljava/util/Map<**>;"));
+ assertEquals("generic signature",
+ "com.jme3.util.IntMap<T>.IntMapIterator",
+ Utility.signatureToString("Lcom/jme3/util/IntMap<TT;>.IntMapIterator;"));
}
}