Skip to content

Commit 01e61c3

Browse files
committed
[GR-61534] Ensure static word fields are not unsafe accessed.
PullRequest: graal/19860
2 parents d544bbe + aba4ec0 commit 01e61c3

File tree

11 files changed

+121
-14
lines changed

11 files changed

+121
-14
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ public boolean registerAsInstantiated(Object reason) {
562562
}
563563

564564
protected void onInstantiated() {
565+
assert !isWordType() : Assertions.errorMessage("Word types cannot be instantiated", this);
565566
forAllSuperTypes(superType -> AtomicUtils.atomicMark(superType, isAnySubtypeInstantiatedUpdater));
566567

567568
universe.onTypeInstantiated(this);
@@ -904,7 +905,9 @@ public final JavaKind getStorageKind() {
904905
*/
905906
public boolean isWordType() {
906907
/* Word types are currently the only types where kind and storageKind differ. */
907-
return getJavaKind() != getStorageKind();
908+
boolean wordType = getJavaKind() != getStorageKind();
909+
assert !wordType || getJavaKind().isObject() : Assertions.errorMessage("Only words are expected to have a discrepancy between java kind and storage kind", this);
910+
return wordType;
908911
}
909912

910913
@Override

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ public void registerEmbeddedRoot(JavaConstant root, BytecodePosition position) {
598598
}
599599

600600
public void registerUnsafeAccessedStaticField(AnalysisField field) {
601+
AnalysisError.guarantee(!field.getType().isWordType(), "static Word fields cannot be unsafe accessed %s", this);
601602
unsafeAccessedStaticFields.put(field, true);
602603
}
603604

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/StaticFieldsSupport.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
3939
import com.oracle.svm.core.feature.InternalFeature;
4040
import com.oracle.svm.core.meta.SharedField;
41+
import com.oracle.svm.core.meta.SharedType;
4142
import com.oracle.svm.core.util.VMError;
4243

4344
import jdk.graal.compiler.core.common.type.StampFactory;
@@ -189,6 +190,26 @@ public void lower(LoweringTool tool) {
189190
replaceAndDelete(ConstantNode.forConstant(constant, tool.getMetaAccess(), graph()));
190191
}
191192
}
193+
194+
/**
195+
* We must ensure we are not querying the offset of a static field of a type assignable from
196+
* {@link org.graalvm.word.WordBase}.
197+
*/
198+
public interface StaticFieldValidator {
199+
static void checkFieldOffsetAllowed(ResolvedJavaField field) {
200+
if (field.isStatic()) {
201+
if (SubstrateUtil.HOSTED) {
202+
ImageSingletons.lookup(StaticFieldValidator.class).hostedCheckFieldOffsetAllowed(field);
203+
} else {
204+
SharedField sField = (SharedField) field;
205+
boolean wordType = ((SharedType) sField.getType()).isWordType();
206+
VMError.guarantee(!wordType, "static Word field offsets cannot be queried");
207+
}
208+
}
209+
}
210+
211+
void hostedCheckFieldOffsetAllowed(ResolvedJavaField field);
212+
}
192213
}
193214

194215
@AutomaticallyRegisteredFeature

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/FieldOffsetNode.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_0;
2828
import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_1;
2929

30+
import com.oracle.svm.core.StaticFieldsSupport;
3031
import com.oracle.svm.core.meta.SharedField;
3132
import com.oracle.svm.core.util.VMError;
3233

@@ -83,6 +84,7 @@ public static ValueNode create(JavaKind kind, ResolvedJavaField field) {
8384
protected FieldOffsetNode(ResolvedJavaField field) {
8485
super(TYPE, StampFactory.forInteger(JavaKind.Long, 0, Integer.MAX_VALUE));
8586
this.field = field;
87+
StaticFieldsSupport.StaticFieldValidator.checkFieldOffsetAllowed(field);
8688
}
8789

8890
@Override

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/VarHandleSupport.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static VarHandleSupport singleton() {
5252
return ImageSingletons.lookup(VarHandleSupport.class);
5353
}
5454

55-
protected abstract ResolvedJavaField findVarHandleField(Object varHandle);
55+
protected abstract ResolvedJavaField findVarHandleField(Object varHandle, boolean guaranteeUnsafeAccessed);
5656
}
5757

5858
abstract class VarHandleFieldOffsetComputer implements FieldValueTransformerWithAvailability {
@@ -70,7 +70,7 @@ public boolean isAvailable() {
7070

7171
@Override
7272
public Object transform(Object receiver, Object originalValue) {
73-
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(receiver);
73+
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(receiver, true);
7474
int offset = field.getOffset();
7575
if (offset <= 0) {
7676
throw VMError.shouldNotReachHere("Field is not marked as unsafe accessed: " + field);
@@ -90,7 +90,7 @@ public Object transform(Object receiver, Object originalValue) {
9090
public ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) {
9191
Object varHandle = providers.getSnippetReflection().asObject(Object.class, receiver);
9292
if (varHandle != null) {
93-
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(varHandle);
93+
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(varHandle, false);
9494
return FieldOffsetNode.create(kind, field);
9595
}
9696
return null;
@@ -117,15 +117,17 @@ public boolean isAvailable() {
117117

118118
@Override
119119
public Object transform(Object receiver, Object originalValue) {
120-
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(receiver);
120+
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(receiver, false);
121+
StaticFieldsSupport.StaticFieldValidator.checkFieldOffsetAllowed(field);
121122
return field.getType().getJavaKind().isPrimitive() ? StaticFieldsSupport.getStaticPrimitiveFields() : StaticFieldsSupport.getStaticObjectFields();
122123
}
123124

124125
@Override
125126
public ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) {
126127
Object varHandle = providers.getSnippetReflection().asObject(Object.class, receiver);
127128
if (varHandle != null) {
128-
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(varHandle);
129+
ResolvedJavaField field = VarHandleSupport.singleton().findVarHandleField(varHandle, false);
130+
StaticFieldsSupport.StaticFieldValidator.checkFieldOffsetAllowed(field);
129131
return StaticFieldsSupport.createStaticFieldBaseNode(field.getType().getJavaKind().isPrimitive());
130132
}
131133
return null;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SharedType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.core.meta;
2626

27+
import org.graalvm.word.WordBase;
28+
2729
import com.oracle.svm.core.hub.DynamicHub;
2830
import com.oracle.svm.core.util.VMError;
2931

@@ -47,6 +49,12 @@ public interface SharedType extends ResolvedJavaType {
4749

4850
int getTypeID();
4951

52+
/**
53+
* Returns true if this type is part of the word type hierarchy, i.e, implements
54+
* {@link WordBase}.
55+
*/
56+
boolean isWordType();
57+
5058
@Override
5159
default ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
5260
/*

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateType.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,18 @@ public void setSingleImplementor(DynamicHub uniqueConcreteImplementation) {
9898
*/
9999
@Override
100100
public final JavaKind getStorageKind() {
101-
if (WordBase.class.isAssignableFrom(DynamicHub.toClass(hub))) {
101+
if (isWordType()) {
102102
return ConfigurationValues.getWordKind();
103103
} else {
104104
return getJavaKind();
105105
}
106106
}
107107

108+
@Override
109+
public boolean isWordType() {
110+
return WordBase.class.isAssignableFrom(DynamicHub.toClass(hub));
111+
}
112+
108113
@Override
109114
public DynamicHub getHub() {
110115
return hub;

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/VarHandleFeature.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,20 @@ public class VarHandleFeature implements InternalFeature {
9797

9898
class VarHandleSupportImpl extends VarHandleSupport {
9999
@Override
100-
protected ResolvedJavaField findVarHandleField(Object varHandle) {
101-
return hUniverse != null ? findVarHandleHostedField(varHandle) : findVarHandleAnalysisField(varHandle);
100+
protected ResolvedJavaField findVarHandleField(Object varHandle, boolean guaranteeUnsafeAccessed) {
101+
ResolvedJavaField result;
102+
if (hUniverse != null) {
103+
result = findVarHandleHostedField(varHandle);
104+
} else {
105+
result = findVarHandleAnalysisField(varHandle);
106+
}
107+
108+
if (guaranteeUnsafeAccessed) {
109+
AnalysisField aField = result instanceof AnalysisField ? (AnalysisField) result : ((HostedField) result).getWrapped();
110+
VMError.guarantee(aField.isUnsafeAccessed(), "Field not registered as unsafe accessed %s", aField);
111+
}
112+
113+
return result;
102114
}
103115
}
104116

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import com.oracle.graal.pointsto.meta.AnalysisMethod;
6262
import com.oracle.graal.pointsto.meta.AnalysisType;
6363
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
64+
import com.oracle.svm.core.StaticFieldsSupport;
6465
import com.oracle.svm.core.SubstrateOptions;
6566
import com.oracle.svm.core.config.ObjectLayout;
6667
import com.oracle.svm.core.configure.ConfigurationConditionResolver;
@@ -512,6 +513,7 @@ private static void addField(Field reflField, boolean writable, DuringAnalysisAc
512513
} else if (field.isStatic() && field.isFinal()) {
513514
MaterializedConstantFields.singleton().register(field);
514515
}
516+
StaticFieldsSupport.StaticFieldValidator.checkFieldOffsetAllowed(field);
515517

516518
BigBang bb = access.getBigBang();
517519
bb.registerAsJNIAccessed(field, writable);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.oracle.svm.core.meta.SharedType;
3636
import com.oracle.svm.core.util.VMError;
3737

38+
import jdk.graal.compiler.debug.Assertions;
3839
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
3940
import jdk.vm.ci.meta.JavaConstant;
4041
import jdk.vm.ci.meta.JavaKind;
@@ -261,13 +262,12 @@ public int[] getOpenTypeWorldTypeCheckSlots() {
261262
return openTypeWorldTypeCheckSlots;
262263
}
263264

264-
/**
265-
* Returns true if this type is part of the word type hierarchy, i.e, implements
266-
* {@link WordBase}.
267-
*/
265+
@Override
268266
public boolean isWordType() {
269267
/* Word types have the kind Object, but a primitive storageKind. */
270-
return kind != storageKind;
268+
boolean wordType = kind != storageKind;
269+
assert !wordType || kind.isObject() : Assertions.errorMessage("Only words are expected to have a discrepancy between java kind and storage kind", this);
270+
return wordType;
271271
}
272272

273273
/**

0 commit comments

Comments
 (0)