Skip to content

Commit de0e648

Browse files
pecimuthDoug Simon
authored andcommitted
8352724: Verify bounds for primitive array reads in JVMCI
Reviewed-by: dnsimon
1 parent 46a6fc8 commit de0e648

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,14 +2253,21 @@ static jobject read_field_value(Handle obj, long displacement, jchar type_char,
22532253
if (!aligned) {
22542254
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "read is unaligned");
22552255
}
2256+
if (obj->is_array()) {
2257+
// Disallow reading after the last element of an array
2258+
size_t array_length = arrayOop(obj())->length();
2259+
int lh = obj->klass()->layout_helper();
2260+
size_t size_in_bytes = array_length << Klass::layout_helper_log2_element_size(lh);
2261+
size_in_bytes += Klass::layout_helper_header_size(lh);
2262+
if ((size_t) displacement + basic_type_elemsize > size_in_bytes) {
2263+
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading after last array element");
2264+
}
2265+
}
22562266
if (basic_type == T_OBJECT) {
22572267
if (obj->is_objArray()) {
22582268
if (displacement < arrayOopDesc::base_offset_in_bytes(T_OBJECT)) {
22592269
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading from array header");
22602270
}
2261-
if (displacement + heapOopSize > arrayOopDesc::base_offset_in_bytes(T_OBJECT) + arrayOop(obj())->length() * heapOopSize) {
2262-
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "reading after last array element");
2263-
}
22642271
if (((displacement - arrayOopDesc::base_offset_in_bytes(T_OBJECT)) % heapOopSize) != 0) {
22652272
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "misaligned object read from array");
22662273
}

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

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,11 +41,7 @@
4141
import java.lang.reflect.Array;
4242
import java.util.List;
4343

44-
import static org.junit.Assert.assertEquals;
45-
import static org.junit.Assert.assertFalse;
46-
import static org.junit.Assert.assertNotNull;
47-
import static org.junit.Assert.assertNull;
48-
import static org.junit.Assert.assertTrue;
44+
import static org.junit.Assert.*;
4945

5046
/**
5147
* Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that
@@ -138,4 +134,42 @@ public void unboxTest() {
138134

139135
assertNull(constantReflection.unboxPrimitive(JavaConstant.NULL_POINTER));
140136
}
137+
138+
static class ArrayConstants {
139+
static final byte[] BYTE_ARRAY_CONST = new byte[]{0};
140+
static final Object[] OBJECT_ARRAY_CONST = new Object[]{null};
141+
}
142+
143+
@Test
144+
public void readOnePastLastArrayElementTest() {
145+
for (ConstantValue cv : readConstants(ArrayConstants.class)) {
146+
if (cv.boxed != null && cv.boxed.getClass().isArray()) {
147+
JavaKind kind = metaAccess.lookupJavaType(cv.value).getComponentType().getJavaKind();
148+
long offset = metaAccess.getArrayBaseOffset(kind) + (long) metaAccess.getArrayIndexScale(kind) * Array.getLength(cv.boxed);
149+
// read array[array.length]
150+
assertThrows(IllegalArgumentException.class, () -> {
151+
if (kind == JavaKind.Object) {
152+
constantReflection.getMemoryAccessProvider().readObjectConstant(cv.value, offset);
153+
} else {
154+
constantReflection.getMemoryAccessProvider().readPrimitiveConstant(kind, cv.value, offset, kind.getBitCount());
155+
}
156+
});
157+
}
158+
}
159+
}
160+
161+
static class IntArrayConstants {
162+
static final int[] INT_ARRAY_CONST = new int[]{0};
163+
}
164+
165+
@Test
166+
public void readPartiallyOutOfBoundsTest() {
167+
for (ConstantValue cv : readConstants(IntArrayConstants.class)) {
168+
JavaKind kind = metaAccess.lookupJavaType(cv.value).getComponentType().getJavaKind();
169+
long offset = metaAccess.getArrayBaseOffset(kind) + (long) metaAccess.getArrayIndexScale(kind) * (Array.getLength(cv.boxed) - 1);
170+
// read a long from array[array.length - 1], which is partially out of bounds
171+
JavaKind accessKind = JavaKind.Long;
172+
assertThrows(IllegalArgumentException.class, () -> constantReflection.getMemoryAccessProvider().readPrimitiveConstant(accessKind, cv.value, offset, accessKind.getBitCount()));
173+
}
174+
}
141175
}

0 commit comments

Comments
 (0)