You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2006/12/17 03:16:08 UTC

svn commit: r487928 - in /harmony/enhanced/drlvm/trunk/vm/vmcore: include/Class.h src/class_support/Prepare.cpp src/jni/jni_array.cpp src/jvmti/jvmti_object.cpp src/object/vm_arrays.cpp src/thread/object_generic.cpp src/util/vm_strings.cpp

Author: gshimansky
Date: Sat Dec 16 18:16:07 2006
New Revision: 487928

URL: http://svn.apache.org/viewvc?view=rev&rev=487928
Log:
Applied HARMONY-2529 [drlvm] crash, very large arrays used incorrectly

I had to make a change to make this patch compile on win32: in Class.h:1681 length was changed to (unsigned)length. Attached test passes after this patch.

Tests passed on Ubuntu6 x86, WindowsXP and SuSE9 x86_64


Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h Sat Dec 16 18:16:07 2006
@@ -930,6 +930,9 @@
     // size of element of array; equals zero, if this class is not an array
     unsigned int m_array_element_size;
 
+    // shift corresponding to size of element of array, undefined for non-arrays
+    unsigned int m_array_element_shift;
+
     // type descriptor for array element class
     TypeDesc* m_array_element_type_desc;
 
@@ -1656,18 +1659,35 @@
      * @param[in] length - the length of the array
      * @return The size of the array of specified length in bytes.*/
     unsigned calculate_array_size(int length) const {
+        if (length < 0) {
+            return 0;
+        }
+
+        assert(m_array_element_size);
         assert(length >= 0);
         assert(is_array());
-        assert(m_array_element_size);
         unsigned first_elem_offset;
-        if(m_array_element_size < 8) {
+        if(m_array_element_shift < 3) {
             first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_1_2_4;
         } else {
             first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_8;
         }
-        unsigned size = first_elem_offset + length*m_array_element_size;
+
+        // check overflow, we need:
+        // first_elem_offset + (length << m_array_element_shift)
+        //      + GC_OBJECT_ALIGNMENT < NEXT_TO_HIGH_BIT_CLEAR_MASK
+        //
+        if (((NEXT_TO_HIGH_BIT_CLEAR_MASK - GC_OBJECT_ALIGNMENT - first_elem_offset)
+                    >> m_array_element_shift) < (unsigned)length) {
+            // zero means overflow
+            return 0;
+        }
+
+
+        unsigned size = first_elem_offset + (length << m_array_element_shift);
         size = (((size + (GC_OBJECT_ALIGNMENT - 1)) & (~(GC_OBJECT_ALIGNMENT - 1))));
         assert((size % GC_OBJECT_ALIGNMENT) == 0);
+        assert((size & NEXT_TO_HIGH_BIT_SET_MASK) == 0);
         return size;
     }
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp Sat Dec 16 18:16:07 2006
@@ -109,38 +109,38 @@
 // Given a class that is a primitive array returns the size
 // of an element in an instance of the class
 // NOTE: the class is not fully formed at this time
-unsigned sizeof_primitive_array_element(Class *p_class) 
+unsigned shift_of_primitive_array_element(Class *p_class) 
 {
     const String *elt_type = p_class->get_name();
     char elt = elt_type->bytes[1];
     unsigned int sz;
     switch (elt) {
     case 'C':
-        sz = 2;
+        sz = 1;
         break;
     case 'B':
-        sz = 1;
+        sz = 0;
         break;
     case 'D':
-        sz = 8;
+        sz = 3;
         break;
     case 'F':
-        sz = 4;
+        sz = 2;
         break;
     case 'I':
-        sz = 4;
+        sz = 2;
         break;
     case 'J':
-        sz = 8;
+        sz = 3;
         break;
     case 'S':
-        sz = 2;
+        sz = 1;
         break;
     case 'Z': // boolean
-        sz = 1;
+        sz = 0;
         break;
     case '[':
-        sz = 4; // This works for the H32, V64, R32 version.
+        sz = 2; // This works for the H32, V64, R32 version.
         assert(OBJECT_REF_SIZE == 4);
         break;
     default:
@@ -148,7 +148,7 @@
         return 0;
     }
     return sz;
-} //sizeof_primitive_array_element
+} //shift_of_primitive_array_element
 
 
 //
@@ -1396,9 +1396,11 @@
     if(is_array()) {
         m_array_element_size = (vm_references_are_compressed()
             ? sizeof(COMPRESSED_REFERENCE) : sizeof(RAW_REFERENCE));
+        m_array_element_shift = m_array_element_size == 8 ? 3 : 2;
         m_vtable->class_properties |= CL_PROP_ARRAY_MASK;
         if(is_vector_of_primitives(this)) {
-            m_array_element_size = sizeof_primitive_array_element(this);
+            m_array_element_shift = shift_of_primitive_array_element(this);
+            m_array_element_size = 1 << m_array_element_shift;
             m_vtable->class_properties |= CL_PROP_NON_REF_ARRAY_MASK;
         }
         m_vtable->array_element_size = (unsigned short)m_array_element_size;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp Sat Dec 16 18:16:07 2006
@@ -239,6 +239,8 @@
     
     Class *clss = vm_env->ArrayOfBoolean_Class;    
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -274,6 +276,8 @@
     
     Class *clss = vm_env->ArrayOfByte_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -309,6 +313,8 @@
 
     Class *clss = vm_env->ArrayOfChar_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -344,6 +350,8 @@
     
     Class *clss = vm_env->ArrayOfShort_Class; 
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
 
@@ -380,6 +388,8 @@
     
     Class *clss = vm_env->ArrayOfInt_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -415,6 +425,8 @@
 
     Class *clss = vm_env->ArrayOfLong_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -450,6 +462,8 @@
     
     Class *clss = vm_env->ArrayOfFloat_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),
@@ -485,6 +499,8 @@
     
     Class *clss = vm_env->ArrayOfDouble_Class;
     unsigned sz = clss->calculate_array_size(length);
+    if (sz == 0) return NULL;
+
     tmn_suspend_disable();       //---------------------------------v
     ObjectHandle h = oh_allocate_local_handle();
     Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(),

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp Sat Dec 16 18:16:07 2006
@@ -79,6 +79,7 @@
         *size_ptr = object_clss->calculate_array_size(get_vector_length((Vector_Handle)mo));
     else
         *size_ptr = class_get_boxed_data_size(object_clss);
+    assert(*size_ptr > 0);
 
     tmn_suspend_enable();
     return JVMTI_ERROR_NONE;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp Sat Dec 16 18:16:07 2006
@@ -71,25 +71,22 @@
     assert(!hythread_is_suspend_enabled());
     assert(!arr_clss->is_array_of_primitives());
 
-    if (length < 0) {
-        tmn_suspend_enable();
-        exn_raise_by_name("java/lang/NegativeArraySizeException");
-        tmn_suspend_disable();
-        return NULL;
-    }
-
     unsigned sz = arr_clss->calculate_array_size(length);
-
-    if ((length & TWO_HIGHEST_BITS_SET_MASK) || (sz & TWO_HIGHEST_BITS_SET_MASK)) {
-        // VM does not support arrays of length >= MAXINT>>2
-        // GC does not support objects of length >= 1Gb
+    if (sz == 0) {
         tmn_suspend_enable();
-        exn_raise_by_name("java/lang/OutOfMemoryError",
-            "VM doesn't support arrays of the requested size");
+
+        if (length < 0) {
+            exn_raise_by_name("java/lang/NegativeArraySizeException");
+        } else {
+            exn_raise_by_name("java/lang/OutOfMemoryError",
+                    "VM doesn't support arrays of the requested size");
+        }
         tmn_suspend_disable();
         return NULL;
     }
 
+    assert((sz & NEXT_TO_HIGH_BIT_SET_MASK) == 0);
+
     Vector_Handle object_array = (Vector_Handle )gc_alloc(sz,
         arr_clss->get_allocation_handle(), vm_get_gc_thread_local());
 #ifdef VM_STATS
@@ -121,20 +118,21 @@
 Vector_Handle vm_new_vector_primitive(Class *vector_class, int length) {
     ASSERT_RAISE_AREA;
     assert(!hythread_is_suspend_enabled());
-    // VM does not support arrays of length >= MAXINT>>2
-    if (length & TWO_HIGHEST_BITS_SET_MASK) {
+    assert(vector_class->is_array_of_primitives());
+    unsigned sz = vector_class->calculate_array_size(length);
+
+    if (sz == 0) {
         tmn_suspend_enable();
         if (length < 0) {
             exn_raise_by_name("java/lang/NegativeArraySizeException");
         } else {
             exn_raise_by_name("java/lang/OutOfMemoryError",
-                "VM doesn't support arrays of the requested size");
+                    "VM doesn't support arrays of the requested size");
         }
         tmn_suspend_disable();
         return NULL;
     }
-    assert(vector_class->is_array_of_primitives());
-    unsigned sz = vector_class->calculate_array_size(length);
+
     Vector_Handle vector = (Vector_Handle)gc_alloc(sz, 
         vector_class->get_allocation_handle(), vm_get_gc_thread_local());
 #ifdef VM_STATS
@@ -184,6 +182,7 @@
     if (0 != (length&TWO_HIGHEST_BITS_SET_MASK)) return;
     VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle);
     unsigned sz = vector_vtable->clss->calculate_array_size(length);
+    assert(sz > 0);
     vector_vtable->clss->instance_allocated(sz);
     if((vector_vtable->class_properties & CL_PROP_NON_REF_ARRAY_MASK) == 0)
     {
@@ -196,21 +195,22 @@
 Vector_Handle vm_new_vector_using_vtable_and_thread_pointer(int length, Allocation_Handle vector_handle, void *tp)
 {
     assert( ! hythread_is_suspend_enabled());
-    // VM does not support arrays of length >= MAXINT>>2
-    if (length & TWO_HIGHEST_BITS_SET_MASK) {
+
+    VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle);
+    unsigned sz = vector_vtable->clss->calculate_array_size(length);
+    if (sz == 0) {
         tmn_suspend_enable();
         if (length < 0) {
             exn_raise_by_name("java/lang/NegativeArraySizeException");
         } else {
             exn_raise_by_name("java/lang/OutOfMemoryError",
-                "VM doesn't support arrays of the requested size");
+                    "VM doesn't support arrays of the requested size");
         }
         tmn_suspend_disable();
         return NULL;
     }
 
-    VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle);
-    unsigned sz = vector_vtable->clss->calculate_array_size(length);
+
 #ifdef VM_STATSxxx // Functionality moved into vm_new_vector_update_stats().
     vector_vtable->clss->instance_allocated(sz);
 #endif //VM_STATS
@@ -233,14 +233,13 @@
 
 Vector_Handle vm_new_vector_or_null_using_vtable_and_thread_pointer(int length, Allocation_Handle vector_handle, void *tp)
 {
-    // VM does not support arrays of length >= MAXINT>>2
-    if (0 != (length&TWO_HIGHEST_BITS_SET_MASK)) {
-        // exception wiil be thown from other method
-        return NULL;
-    }
-
     VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle);
     unsigned sz = vector_vtable->clss->calculate_array_size(length);
+
+    if (sz == 0) {
+        // Unsupported size
+        return NULL;
+    }
     Vector_Handle vector = (Vector_Handle)gc_alloc_fast(sz, vector_handle, tp);
     if (vector == NULL)
     {

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp Sat Dec 16 18:16:07 2006
@@ -129,6 +129,7 @@
         // clone an array
         int32 length = get_vector_length((Vector_Handle) h->object);
         size = vt->clss->calculate_array_size(length);
+        assert(size > 0);
         result = (ManagedObject*)
             vm_new_vector_using_vtable_and_thread_pointer(length,
                 vt->clss->get_allocation_handle(), vm_get_gc_thread_local());

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp?view=diff&rev=487928&r1=487927&r2=487928
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp Sat Dec 16 18:16:07 2006
@@ -244,6 +244,13 @@
     assert(clss);
 
     unsigned sz = clss->calculate_array_size(unicode_length);
+    if (sz == 0) {
+        // string too long
+        *str = NULL;
+        exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError);
+        return;
+    }
+
     Vector_Handle array = vm_alloc_and_report_ti(sz, clss->get_allocation_handle(),
         vm_get_gc_thread_local(), clss);
     if(!array) { // OutOfMemory should be thrown