Mercurial > hg > graal-jvmci-8
changeset 24111:8abcd8e1285d
missing checks in HotSpotMemoryAccessProviderImpl can cause VM assertions to fail (JDK-8177673)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 30 Mar 2017 21:18:43 +0200 |
parents | a8378ff1936d |
children | c0b9eb2b6715 |
files | jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MemoryAccessProvider.java |
diffstat | 4 files changed, 70 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java Mon Mar 20 10:46:02 2017 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java Thu Mar 30 21:18:43 2017 +0200 @@ -31,6 +31,10 @@ */ public interface HotSpotMemoryAccessProvider extends MemoryAccessProvider { + /** + * @throws IllegalArgumentException if the address computed from {@code base} and + * {@code displacement} does not denote a location holding a narrow oop + */ JavaConstant readNarrowOopConstant(Constant base, long displacement); Constant readKlassPointerConstant(Constant base, long displacement);
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java Mon Mar 20 10:46:02 2017 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java Thu Mar 30 21:18:43 2017 +0200 @@ -22,12 +22,20 @@ */ package jdk.vm.ci.hotspot; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; + +import java.lang.reflect.Array; + import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.PrimitiveConstant; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; /** * HotSpot implementation of {@link MemoryAccessProvider}. @@ -40,12 +48,48 @@ this.runtime = runtime; } - private static Object asObject(Constant base) { + /** + * Gets the object boxed by {@code base} that is about to have a value of kind {@code kind} read + * from it at the offset {@code displacement}. + * + * @param base constant value containing the base address for a pending read + * @return {@code null} if {@code base} does not box an object otherwise the object boxed in + * {@code base} + * @throws IllegalArgumentException if {@code base} boxes an object and the read address does + * not correspond to a field or element within the object + */ + private static Object asObject(MetaAccessProvider metaAccess, Constant base, JavaKind kind, long displacement) { if (base instanceof HotSpotObjectConstantImpl) { - return ((HotSpotObjectConstantImpl) base).object(); - } else { - return null; + HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base; + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); + Object object = constant.object(); + if (type.isArray()) { + ResolvedJavaType componentType = type.getComponentType(); + JavaKind componentKind = componentType.getJavaKind(); + final int headerSize = getArrayBaseOffset(componentKind); + int sizeOfElement = getArrayIndexScale(componentKind); + int length = Array.getLength(object); + int index = (int) ((displacement - headerSize) / sizeOfElement); + if (displacement < headerSize || index >= length || ((displacement - headerSize) % sizeOfElement) != 0) { + throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind + + " at offset " + displacement + " (index ~ " + index + ") in " + + type.toJavaName() + " object of length " + length); + } + } else { + ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, kind); + if (field == null && object instanceof Class) { + HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object); + field = staticFieldsHolder.findStaticFieldWithOffset(displacement, kind); + } + if (field == null) { + throw new IllegalArgumentException("Unsafe object access: field not found for read of kind " + kind + + " at offset " + displacement + " in " + + type.toJavaName() + " object"); + } + } + return object; } + return null; } private boolean isValidObjectFieldDisplacement(Constant base, long displacement) { @@ -79,8 +123,8 @@ throw new IllegalArgumentException(String.valueOf(base)); } - private static long readRawValue(Constant baseConstant, long displacement, int bits) { - Object base = asObject(baseConstant); + private static long readRawValue(MetaAccessProvider metaAccess, Constant baseConstant, long displacement, JavaKind kind, int bits) { + Object base = asObject(metaAccess, baseConstant, kind, displacement); if (base != null) { switch (bits) { case Byte.SIZE: @@ -127,9 +171,8 @@ private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) { long displacement = initialDisplacement; - Object ret; - Object base = asObject(baseConstant); + Object base = asObject(runtime.getHostJVMCIBackend().getMetaAccess(), baseConstant, JavaKind.Object, displacement); if (base == null) { assert !compressed; displacement += asRawPointer(baseConstant); @@ -152,6 +195,8 @@ * value cannot be read. * @throws IllegalArgumentException if {@code kind} is {@code null}, {@link JavaKind#Void}, not * {@link JavaKind#Object} or not {@linkplain JavaKind#isPrimitive() primitive} kind + * or if {@code baseConstant} is a boxed object and the read address does not denote + * a field or element within the object */ JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) { if (kind == null) { @@ -169,7 +214,7 @@ @Override public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) { try { - long rawValue = readRawValue(baseConstant, initialDisplacement, bits); + long rawValue = readRawValue(runtime.getHostJVMCIBackend().getMetaAccess(), baseConstant, initialDisplacement, kind, bits); switch (kind) { case Boolean: return JavaConstant.forBoolean(rawValue != 0); @@ -190,7 +235,7 @@ default: throw new IllegalArgumentException("Unsupported kind: " + kind); } - } catch (NullPointerException e) { + } catch (IllegalArgumentException | NullPointerException e) { return null; } }
--- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Mon Mar 20 10:46:02 2017 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Mar 30 21:18:43 2017 +0200 @@ -842,6 +842,15 @@ @Override public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedEntryKind) { ResolvedJavaField[] declaredFields = getInstanceFields(true); + return findFieldWithOffset(offset, expectedEntryKind, declaredFields); + } + + public ResolvedJavaField findStaticFieldWithOffset(long offset, JavaKind expectedEntryKind) { + ResolvedJavaField[] declaredFields = getStaticFields(); + return findFieldWithOffset(offset, expectedEntryKind, declaredFields); + } + + private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) { for (ResolvedJavaField field : declaredFields) { HotSpotResolvedJavaField resolvedField = (HotSpotResolvedJavaField) field; long resolvedFieldOffset = resolvedField.offset();
--- a/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MemoryAccessProvider.java Mon Mar 20 10:46:02 2017 +0100 +++ b/jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MemoryAccessProvider.java Thu Mar 30 21:18:43 2017 +0200 @@ -35,6 +35,8 @@ * @param displacement the displacement within the object in bytes * @param bits the number of bits to read from memory * @return the read value encapsulated in a {@link JavaConstant} object of {@link JavaKind} kind + * or {@code null} if {@code base} is a boxed object and the read address does not + * denote a location holding an {@code kind} value * @throws IllegalArgumentException if {@code kind} is {@link JavaKind#Void} or not * {@linkplain JavaKind#isPrimitive() primitive} kind or {@code bits} is not 8, 16, * 32 or 64