Skip to content

Commit 5cf349c

Browse files
author
Doug Simon
committed
8361355: Negative cases of Annotated.getAnnotationData implementations are broken
Reviewed-by: never
1 parent 21f2e9a commit 5cf349c

File tree

7 files changed

+110
-17
lines changed

7 files changed

+110
-17
lines changed

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
2626
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
2727
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
28+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkAreAnnotations;
29+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkIsAnnotation;
30+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.getFirstAnnotationOrNull;
2831
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
2932
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
3033

@@ -234,15 +237,19 @@ public JavaConstant getConstantValue() {
234237
@Override
235238
public AnnotationData getAnnotationData(ResolvedJavaType annotationType) {
236239
if (!hasAnnotations()) {
240+
checkIsAnnotation(annotationType);
237241
return null;
238242
}
239-
return getAnnotationData0(annotationType).get(0);
243+
return getFirstAnnotationOrNull(getAnnotationData0(annotationType));
240244
}
241245

242246
@Override
243247
public List<AnnotationData> getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) {
248+
checkIsAnnotation(type1);
249+
checkIsAnnotation(type2);
250+
checkAreAnnotations(types);
244251
if (!hasAnnotations()) {
245-
return Collections.emptyList();
252+
return List.of();
246253
}
247254
return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types));
248255
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
import static jdk.vm.ci.hotspot.HotSpotModifiers.SYNTHETIC;
2929
import static jdk.vm.ci.hotspot.HotSpotModifiers.VARARGS;
3030
import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmMethodModifiers;
31+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkAreAnnotations;
32+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.checkIsAnnotation;
33+
import static jdk.vm.ci.hotspot.HotSpotResolvedJavaType.getFirstAnnotationOrNull;
3134
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
3235
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
3336

@@ -775,15 +778,19 @@ public int methodIdnum() {
775778
@Override
776779
public AnnotationData getAnnotationData(ResolvedJavaType type) {
777780
if (!hasAnnotations()) {
781+
checkIsAnnotation(type);
778782
return null;
779783
}
780-
return getAnnotationData0(type).get(0);
784+
return getFirstAnnotationOrNull(getAnnotationData0(type));
781785
}
782786

783787
@Override
784788
public List<AnnotationData> getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) {
789+
checkIsAnnotation(type1);
790+
checkIsAnnotation(type2);
791+
checkAreAnnotations(types);
785792
if (!hasAnnotations()) {
786-
return Collections.emptyList();
793+
return List.of();
787794
}
788795
return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types));
789796
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
*/
2323
package jdk.vm.ci.hotspot;
2424

25+
import java.util.List;
26+
27+
import jdk.vm.ci.meta.AnnotationData;
2528
import jdk.vm.ci.meta.JavaConstant;
2629
import jdk.vm.ci.meta.ResolvedJavaType;
2730

@@ -61,4 +64,20 @@ public final HotSpotResolvedObjectType getArrayClass() {
6164
* @return {@code true} if this type is being initialized
6265
*/
6366
abstract boolean isBeingInitialized();
67+
68+
static void checkIsAnnotation(ResolvedJavaType type) {
69+
if (!type.isAnnotation()) {
70+
throw new IllegalArgumentException(type.toJavaName() + " is not an annotation interface");
71+
}
72+
}
73+
74+
static void checkAreAnnotations(ResolvedJavaType... types) {
75+
for (ResolvedJavaType type : types) {
76+
checkIsAnnotation(type);
77+
}
78+
}
79+
80+
static AnnotationData getFirstAnnotationOrNull(List<AnnotationData> list) {
81+
return list.isEmpty() ? null : list.get(0);
82+
}
6483
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,15 +1120,19 @@ public boolean isCloneableWithAllocation() {
11201120
@Override
11211121
public AnnotationData getAnnotationData(ResolvedJavaType annotationType) {
11221122
if (!mayHaveAnnotations(true)) {
1123+
checkIsAnnotation(annotationType);
11231124
return null;
11241125
}
1125-
return getAnnotationData0(annotationType).get(0);
1126+
return getFirstAnnotationOrNull(getAnnotationData0(annotationType));
11261127
}
11271128

11281129
@Override
11291130
public List<AnnotationData> getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) {
11301131
if (!mayHaveAnnotations(true)) {
1131-
return Collections.emptyList();
1132+
checkIsAnnotation(type1);
1133+
checkIsAnnotation(type2);
1134+
checkAreAnnotations(types);
1135+
return List.of();
11321136
}
11331137
return getAnnotationData0(AnnotationDataDecoder.asArray(type1, type2, types));
11341138
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,12 +327,15 @@ JavaConstant getJavaMirror() {
327327

328328
@Override
329329
public AnnotationData getAnnotationData(ResolvedJavaType type) {
330+
checkIsAnnotation(type);
330331
return null;
331332
}
332333

333334
@Override
334335
public List<AnnotationData> getAnnotationData(ResolvedJavaType type1, ResolvedJavaType type2, ResolvedJavaType... types) {
335-
return Collections.emptyList();
336+
checkIsAnnotation(type1);
337+
checkIsAnnotation(type2);
338+
checkAreAnnotations(types);
339+
return List.of();
336340
}
337-
338341
}

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
5050
*/
5151
AssumptionResult<Boolean> hasFinalizableSubclass();
5252

53+
/**
54+
* Returns true if this type represents an annotation interface.
55+
*
56+
* @return {@code true} if this type represents an annotation interface
57+
*/
58+
default boolean isAnnotation() {
59+
return (getModifiers() & java.lang.reflect.AccessFlag.ANNOTATION.mask()) != 0;
60+
}
61+
5362
/**
5463
* Checks whether this type is an interface.
5564
*

test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ public void findInstanceFieldWithOffsetTest() {
158158
}
159159
}
160160

161+
@Test
162+
public void isAnnotationTest() {
163+
for (Class<?> c : classes) {
164+
ResolvedJavaType type = metaAccess.lookupJavaType(c);
165+
boolean expected = c.isAnnotation();
166+
boolean actual = type.isAnnotation();
167+
assertEquals(expected, actual);
168+
}
169+
}
170+
161171
@Test
162172
public void isInterfaceTest() {
163173
for (Class<?> c : classes) {
@@ -1267,25 +1277,59 @@ private static boolean isSignaturePolymorphic(ResolvedJavaMethod method) {
12671277
return method.getAnnotation(SIGNATURE_POLYMORPHIC_CLASS) != null;
12681278
}
12691279

1280+
private static void getAnnotationDataExpectedToFail(Annotated annotated, ResolvedJavaType... annotationTypes) {
1281+
try {
1282+
if (annotationTypes.length == 1) {
1283+
annotated.getAnnotationData(annotationTypes[0]);
1284+
} else {
1285+
var tail = Arrays.copyOfRange(annotationTypes, 2, annotationTypes.length);
1286+
annotated.getAnnotationData(annotationTypes[0], annotationTypes[1], tail);
1287+
}
1288+
String s = Stream.of(annotationTypes).map(ResolvedJavaType::toJavaName).collect(Collectors.joining(", "));
1289+
throw new AssertionError("Expected IllegalArgumentException for retrieving (" + s + " from " + annotated);
1290+
} catch (IllegalArgumentException iae) {
1291+
assertTrue(iae.getMessage(), iae.getMessage().contains("not an annotation interface"));
1292+
}
1293+
}
1294+
12701295
/**
12711296
* Tests that {@link AnnotationData} obtained from a {@link Class}, {@link Method} or
12721297
* {@link Field} matches {@link AnnotatedElement#getAnnotations()} for the corresponding JVMCI
12731298
* object.
12741299
*
1275-
* @param annotated a {@link Class}, {@link Method} or {@link Field} object
1300+
* @param annotatedElement a {@link Class}, {@link Method} or {@link Field} object
12761301
*/
1277-
public static void getAnnotationDataTest(AnnotatedElement annotated) throws Exception {
1278-
testGetAnnotationData(annotated, List.of(annotated.getAnnotations()));
1279-
}
1280-
1281-
private static void testGetAnnotationData(AnnotatedElement annotated, List<Annotation> annotations) throws AssertionError {
1302+
public static void getAnnotationDataTest(AnnotatedElement annotatedElement) throws Exception {
1303+
Annotated annotated = toAnnotated(annotatedElement);
1304+
ResolvedJavaType objectType = metaAccess.lookupJavaType(Object.class);
1305+
ResolvedJavaType suppressWarningsType = metaAccess.lookupJavaType(SuppressWarnings.class);
1306+
getAnnotationDataExpectedToFail(annotated, objectType);
1307+
getAnnotationDataExpectedToFail(annotated, suppressWarningsType, objectType);
1308+
getAnnotationDataExpectedToFail(annotated, suppressWarningsType, suppressWarningsType, objectType);
1309+
1310+
// Check that querying a missing annotation returns null or an empty list
1311+
assertNull(annotated.getAnnotationData(suppressWarningsType));
1312+
List<AnnotationData> data = annotated.getAnnotationData(suppressWarningsType, suppressWarningsType);
1313+
assertTrue(data.toString(), data.isEmpty());
1314+
data = annotated.getAnnotationData(suppressWarningsType, suppressWarningsType, suppressWarningsType, suppressWarningsType);
1315+
assertTrue(data.toString(), data.isEmpty());
1316+
1317+
testGetAnnotationData(annotatedElement, annotated, List.of(annotatedElement.getAnnotations()));
1318+
}
1319+
1320+
private static void testGetAnnotationData(AnnotatedElement annotatedElement, Annotated annotated, List<Annotation> annotations) throws AssertionError {
1321+
ResolvedJavaType suppressWarningsType = metaAccess.lookupJavaType(SuppressWarnings.class);
12821322
for (Annotation a : annotations) {
1283-
AnnotationData ad = toAnnotated(annotated).getAnnotationData(metaAccess.lookupJavaType(a.annotationType()));
1323+
var annotationType = metaAccess.lookupJavaType(a.annotationType());
1324+
AnnotationData ad = annotated.getAnnotationData(annotationType);
12841325
assertAnnotationsEquals(a, ad);
12851326

12861327
// Check that encoding/decoding produces a stable result
1287-
AnnotationData ad2 = toAnnotated(annotated).getAnnotationData(metaAccess.lookupJavaType(a.annotationType()));
1328+
AnnotationData ad2 = annotated.getAnnotationData(annotationType);
12881329
assertEquals(ad, ad2);
1330+
1331+
List<AnnotationData> annotationData = annotated.getAnnotationData(annotationType, suppressWarningsType, suppressWarningsType);
1332+
assertEquals(1, annotationData.size());
12891333
}
12901334
if (annotations.size() < 2) {
12911335
return;
@@ -1298,7 +1342,7 @@ private static void testGetAnnotationData(AnnotatedElement annotated, List<Annot
12981342
subList(2, i + 1).//
12991343
stream().map(a -> metaAccess.lookupJavaType(a.annotationType())).//
13001344
toArray(ResolvedJavaType[]::new);
1301-
List<AnnotationData> annotationData = toAnnotated(annotated).getAnnotationData(type1, type2, types);
1345+
List<AnnotationData> annotationData = annotated.getAnnotationData(type1, type2, types);
13021346
assertEquals(2 + types.length, annotationData.size());
13031347

13041348
for (int j = 0; j < annotationData.size(); j++) {

0 commit comments

Comments
 (0)