changeset 16615:3812931f9350

Don't read beyond end of known vtable
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Tue, 29 Jul 2014 17:40:00 -0700
parents 0f2a9150d6f8
children 29404eec7ced
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java
diffstat 3 files changed, 22 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Jul 29 17:39:11 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Jul 29 17:40:00 2014 -0700
@@ -848,6 +848,8 @@
     @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize;
     @HotSpotVMField(name = "vtableEntry::_method", type = "Method*", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset;
     @HotSpotVMValue(expression = "InstanceKlass::vtable_start_offset() * HeapWordSize") @Stable public int instanceKlassVtableStartOffset;
+    @HotSpotVMValue(expression = "InstanceKlass::vtable_length_offset() * HeapWordSize") @Stable public int instanceKlassVtableLengthOffset;
+    @HotSpotVMValue(expression = "Universe::base_vtable_size() / vtableEntry::size()") @Stable public int baseVtableLength;
 
     /**
      * The offset of the array length word in an array object's header.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 29 17:39:11 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Tue Jul 29 17:40:00 2014 -0700
@@ -612,21 +612,26 @@
     public int vtableEntryOffset(ResolvedJavaType resolved) {
         guarantee(isInVirtualMethodTable(resolved), "%s does not have a vtable entry", this);
         HotSpotVMConfig config = runtime().getConfig();
-        final int vtableIndex = getVtableIndex(resolved);
+        final int vtableIndex = getVtableIndex((HotSpotResolvedObjectType) resolved);
         return config.instanceKlassVtableStartOffset + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
     }
 
     @Override
     public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
-        return getVtableIndex(resolved) >= 0;
+        if (resolved instanceof HotSpotResolvedObjectType) {
+            HotSpotResolvedObjectType hotspotResolved = (HotSpotResolvedObjectType) resolved;
+            int vtableIndex = getVtableIndex(hotspotResolved);
+            return vtableIndex >= 0 && vtableIndex < hotspotResolved.getVtableLength();
+        }
+        return false;
     }
 
-    private int getVtableIndex(ResolvedJavaType resolved) {
+    private int getVtableIndex(HotSpotResolvedObjectType resolved) {
         if (!holder.isLinked()) {
             return runtime().getConfig().invalidVtableIndex;
         }
         if (holder.isInterface()) {
-            if (resolved.isArray() || resolved.isInterface()) {
+            if (resolved.isInterface()) {
                 return runtime().getConfig().invalidVtableIndex;
             }
             return getVtableIndexForInterface(resolved);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jul 29 17:39:11 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Tue Jul 29 17:40:00 2014 -0700
@@ -436,6 +436,17 @@
         return method;
     }
 
+    public int getVtableLength() {
+        HotSpotVMConfig config = runtime().getConfig();
+        if (isInterface() || isArray()) {
+            /* Everything has the core vtable of java.lang.Object */
+            return config.baseVtableLength;
+        }
+        int result = unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) / (config.vtableEntrySize / config.heapWordSize);
+        assert result >= config.baseVtableLength : unsafe.getInt(getMetaspaceKlass() + config.instanceKlassVtableLengthOffset) + " " + config.vtableEntrySize;
+        return result;
+    }
+
     /**
      * Gets the mask used to filter out HotSpot internal flags for fields when a {@link Field}
      * object is created. This is the value of {@code JVM_RECOGNIZED_FIELD_MODIFIERS} in