diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java index fd1e612997ac4..4f37ad2e1430b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SignaturesImpl.java @@ -44,49 +44,64 @@ public SignaturesImpl() { public ClassSignature parseClassSignature(String signature) { this.sig = signature; sigp = 0; - List typeParamTypes = parseParamTypes(); - RefTypeSig superclass = referenceTypeSig(); - ArrayList superinterfaces = null; - while (sigp < sig.length()) { - if (superinterfaces == null) - superinterfaces = new ArrayList<>(); - superinterfaces.add(referenceTypeSig()); + try { + List typeParamTypes = parseParamTypes(); + RefTypeSig superclass = referenceTypeSig(); + ArrayList superinterfaces = null; + while (sigp < sig.length()) { + if (superinterfaces == null) + superinterfaces = new ArrayList<>(); + superinterfaces.add(referenceTypeSig()); + } + return new ClassSignatureImpl(typeParamTypes, superclass, null2Empty(superinterfaces)); + } catch (IndexOutOfBoundsException e) { + throw error("Not a valid class signature"); } - return new ClassSignatureImpl(typeParamTypes, superclass, null2Empty(superinterfaces)); } public MethodSignature parseMethodSignature(String signature) { this.sig = signature; sigp = 0; - List typeParamTypes = parseParamTypes(); - assert sig.charAt(sigp) == '('; - sigp++; - ArrayList paramTypes = null; - while (sig.charAt(sigp) != ')') { - if (paramTypes == null) - paramTypes = new ArrayList<>(); - paramTypes.add(typeSig()); - } - sigp++; - Signature returnType = typeSig(); - ArrayList throwsTypes = null; - while (sigp < sig.length() && sig.charAt(sigp) == '^') { + try { + List typeParamTypes = parseParamTypes(); + if (sig.charAt(sigp) != '(') throw error("Expected ( at possition %d of signature".formatted(sigp)); + sigp++; + ArrayList paramTypes = null; + while (sig.charAt(sigp) != ')') { + if (paramTypes == null) + paramTypes = new ArrayList<>(); + paramTypes.add(typeSig()); + } sigp++; - if (throwsTypes == null) - throwsTypes = new ArrayList<>(); - var t = typeSig(); - if (t instanceof ThrowableSig ts) - throwsTypes.add(ts); - else - throw new IllegalArgumentException("not a valid type signature: " + sig); + Signature returnType = typeSig(); + ArrayList throwsTypes = null; + while (sigp < sig.length()) { + if (sig.charAt(sigp) != '^') throw error("Expected ^ at possition %d of signature".formatted(sigp)); + sigp++; + if (throwsTypes == null) + throwsTypes = new ArrayList<>(); + var t = referenceTypeSig(); + if (t instanceof ThrowableSig ts) + throwsTypes.add(ts); + else + throw error("Not a valid throwable signature %s in".formatted(t.signatureString())); + } + return new MethodSignatureImpl(typeParamTypes, null2Empty(throwsTypes), returnType, null2Empty(paramTypes)); + } catch (IndexOutOfBoundsException e) { + throw error("Not a valid method signature"); } - return new MethodSignatureImpl(typeParamTypes, null2Empty(throwsTypes), returnType, null2Empty(paramTypes)); } public Signature parseSignature(String signature) { this.sig = signature; sigp = 0; - return typeSig(); + try { + var s = typeSig(); + if (sigp == signature.length()) + return s; + } catch (IndexOutOfBoundsException e) { + } + throw error("Not a valid type signature"); } private List parseParamTypes() { @@ -157,7 +172,7 @@ private RefTypeSig referenceTypeSig() { return ty; case '[': return ArrayTypeSig.of(typeSig()); } - throw new IllegalArgumentException("not a valid type signature: " + sig); + throw error("Unexpected character %c at possition %d of signature".formatted(c, sigp - 1)); } private TypeArg typeArg() { @@ -292,4 +307,8 @@ public String signatureString() { private static List null2Empty(ArrayList l) { return l == null ? List.of() : Collections.unmodifiableList(l); } + + private IllegalArgumentException error(String message) { + return new IllegalArgumentException("%s: %s".formatted(message, sig)); + } } diff --git a/test/jdk/jdk/classfile/SignaturesTest.java b/test/jdk/jdk/classfile/SignaturesTest.java index 9f5fbe8adcae2..4688f704036a6 100644 --- a/test/jdk/jdk/classfile/SignaturesTest.java +++ b/test/jdk/jdk/classfile/SignaturesTest.java @@ -24,6 +24,7 @@ /* * @test * @summary Testing Signatures. + * @bug 8321540 * @run junit SignaturesTest */ import java.io.IOException; @@ -46,8 +47,11 @@ import java.lang.classfile.Attributes; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Assertions; import static helpers.ClassRecord.assertEqualsDeep; import static java.lang.constant.ConstantDescs.*; +import java.util.function.Consumer; +import java.util.function.Function; class SignaturesTest { @@ -186,4 +190,79 @@ void testClassSignatureClassDesc() throws IOException { assertEquals(Outer.Inner.class.describeConstable().orElseThrow(), innerSig.classDesc(), "ClassDesc derived from signature"); } + + @Test + void testBadTypeSignatures() { + """ + LObject + LObject;B + LIterable + LIterable<< + TBar + TBar + B + B;V + X + [LObject + [LIterable + [LIterable<< + [TBar + [TBar + [B + [X + LSet<+Kind<**>;>; + LSet;>; + ()V + """.lines().forEach(assertThrows(Signature::parseFrom)); + } + + @Test + void testBadClassSignatures() { + """ + Ljava/lang/Object;Ljava/lang/Iterable + LObject + LObject;B + LIterable + LIterable<< + TBar + TBar + B + B;V + X + LFoo.It;L + LFoo;LFoo;LBar; + >LFoo; + LFoo<+>; + ()V + """.lines().forEach(assertThrows(ClassSignature::parseFrom)); + } + + @Test + void testBadMethodSignatures() { + """ + LObject; + B + ()V^ + ()V^B + ()V^X + (LObject;) + (LObject)V + ()LIterable + ()LIterable<< + ()TBar + ()TBar;B + (TBar)V + (B)V + (X) + ()X + ()VB + ()LSet<+Kind<**>;>; + (LSet;>;)V + ()V + """.lines().forEach(assertThrows(MethodSignature::parseFrom)); + } + + private Consumer assertThrows(Function parser) { + return s -> Assertions.assertThrows(IllegalArgumentException.class, () -> parser.apply(s), s); + } }