You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2007/08/06 05:01:53 UTC

svn commit: r563013 - in /harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363: Pass2.cpp context.h tpool.cpp tpool.h

Author: mloenko
Date: Sun Aug  5 20:01:52 2007
New Revision: 563013

URL: http://svn.apache.org/viewvc?view=rev&rev=563013
Log:
fixed HARMONY-4537 and HARMONY-4538 (access to super class members)

Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp?view=diff&rev=563013&r1=563012&r2=563013
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp Sun Aug  5 20:01:52 2007
@@ -1520,7 +1520,10 @@
             if( !tpool.cpool_get_field(cp_idx, &ref, &value) ) return error(VF_ErrorUnknown, "incorrect constantpool entry");
 
             //pop INs
-            POP_ref(ref);
+             vf_Result result;
+             if( (result = popFieldRef(ref, cp_idx)) != VF_OK ) {
+                return result;
+             }
 
             //push OUTs
             PUSH_z(value);
@@ -1556,7 +1559,10 @@
             }
 
             if( workmap_stackview(0).getAnyPossibleValue() != SM_THISUNINIT ) {
-                POP_ref(expected_ref);
+                vf_Result result;
+                if( (result = popFieldRef(expected_ref, cp_idx)) != VF_OK ) {
+                    return result;
+                }
             } else if( expected_ref == tpool.sm_get_const_this() ) {
                 workmap_pop();
             } else {
@@ -1703,18 +1709,22 @@
                 } else {
                     if( expected_ref != wm_init.getConst() ) return error(VF_ErrorUnknown, "incorrect uninitialized type");
                 }
+            } else if( opcode == OP_INVOKESPECIAL ) {
+                //pop object ref (it must extend be either 'this' or a sub class of 'this')
+                POP_ref( tpool.sm_get_const_this() );
+                    
+                //check that 'expected_ref' is a super class of 'this'
+                if( !tpool.mustbe_assignable(tpool.sm_get_const_this(), expected_ref) ) {
+                    return error(VF_ErrorUnknown, "incorrect use of invokespecial");
+                }
+            } else if( opcode == OP_INVOKEVIRTUAL ) {
+                vf_Result result;
+                if( (result = popVirtualRef(expected_ref, cp_idx)) != VF_OK ) {
+                    return result;
+                }
             } else if( opcode != OP_INVOKESTATIC ) {
                 //pop object ref
                 POP_ref( expected_ref );
-
-                if( opcode == OP_INVOKESPECIAL ) {
-                    //TODO: is verifier the right place for this check?
-                    
-                    //check that 'expected_ref' is a super class of 'this'
-                    if( !tpool.mustbe_assignable(tpool.sm_get_const_this(), expected_ref) ) {
-                        return error(VF_ErrorUnknown, "incorrect use of invokespecial");
-                    }
-                }
             }
 
             //push OUTs
@@ -2559,4 +2569,60 @@
             return VF_OK;
         }
 
+        vf_Result vf_Context_t::popFieldRef(SmConstant expected_ref, unsigned short cp_idx) {
+            int check = tpool.checkFieldAccess( expected_ref, cp_idx);
+            if ( check == vf_TypePool::_BOGUS ) return error(VF_ErrorResolve, "can't resolve constantpool class");
+
+            if( check != vf_TypePool::_FALSE ) {
+                assert(check == vf_TypePool::_TRUE);
+
+                //pop object ref (it must extend be either 'this' or a sub class of 'this')
+                POP_ref( tpool.sm_get_const_this() );
+
+                //check that 'expected_ref' is a super class of 'this'
+                if( !tpool.mustbe_assignable(tpool.sm_get_const_this(), expected_ref) ) {
+                    return error(VF_ErrorUnknown, "incorrect use of invokespecial");
+                }
+            } else {
+                POP_ref( expected_ref );
+            }
+            return VF_OK;
+        }
+
+
+        vf_Result vf_Context_t::popVirtualRef(SmConstant expected_ref, unsigned short cp_idx) {
+            int check = tpool.checkVirtualAccess( expected_ref, cp_idx);
+            if ( check == vf_TypePool::_BOGUS ) return error(VF_ErrorResolve, "can't resolve constantpool class");
+
+            if( check != vf_TypePool::_FALSE ) {
+                if( !workmap_can_pop(1) ) return error(VF_ErrorDataFlow, "unable to pop from empty operand stack");
+                WorkmapElement value = workmap_pop();
+
+                if( check == vf_TypePool::_CLONE ) {
+                    //if the first value is an array ==> expect array here
+                    SmConstant c = value.getAnyPossibleValue();
+                    if( c.isReference() && tpool.sm_get_refname(c)[0] == '[' ) {
+                        if( !workmap_expect(value, SM_ANYARRAY) ) return error(VF_ErrorIncompatibleArgument, "incompartible argument");
+                        if( !workmap_expect(value, expected_ref) ) return error(VF_ErrorIncompatibleArgument, "incompartible argument");
+                    } else {
+                        check = vf_TypePool::_TRUE;
+                    }
+                }
+
+                if ( check != vf_TypePool::_CLONE ) {
+                    assert(check == vf_TypePool::_TRUE);
+
+                    //pop object ref (it must extend be either 'this' or a sub class of 'this')
+                    if( !workmap_expect(value, tpool.sm_get_const_this()) ) return error(VF_ErrorIncompatibleArgument, "incompartible argument");
+
+                    //check that 'expected_ref' is a super class of 'this'
+                    if( !tpool.mustbe_assignable(tpool.sm_get_const_this(), expected_ref) ) {
+                        return error(VF_ErrorUnknown, "incorrect use of invokespecial");
+                    }
+                }
+            } else {
+                POP_ref( expected_ref );
+            }
+            return VF_OK;
+        }
 } // namespace CPVerifier

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h?view=diff&rev=563013&r1=563012&r2=563013
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h Sun Aug  5 20:01:52 2007
@@ -295,6 +295,14 @@
 
         /////////////////////////////////////////////////////////////////////////////////////////////////////
 
+        //check conditions for accessing protected non-static fields in different package
+        vf_Result popFieldRef(SmConstant expected_ref, unsigned short cp_idx);
+
+        //check conditions for accessing protected virtual methods in different package
+        vf_Result popVirtualRef(SmConstant expected_ref, unsigned short cp_idx);
+
+        /////////////////////////////////////////////////////////////////////////////////////////////////////
+
         //add one more possible value (type) that can come to the given point (local or stack)
         vf_Result add_incoming_value(SmConstant new_value, StackmapElement *destination);
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp?view=diff&rev=563013&r1=563012&r2=563013
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp Sun Aug  5 20:01:52 2007
@@ -261,6 +261,76 @@
         }
     }
 
+    //check if expected_ref is a super class of 'this', its package differs
+    int vf_TypePool::checkSuperAndPackage(SmConstant expected_ref) {
+        //check that expected ref is a super of 'this'
+        vf_ValidType *expected_type = &validTypes[expected_ref.getReferenceIdx()];
+
+        if (!class_is_extending_class(k_class, (char*)expected_type->name)) {
+            return _FALSE;
+        }
+
+        class_handler &referred = expected_type->cls;
+
+        if( !referred || referred == CLASS_NOT_LOADED ) {
+            //we need to ersolve class here
+            referred = vf_resolve_class(k_class, expected_type->name, true);
+
+            //referred class can't be resolved ==> return anything
+            if( !referred ) return _BOGUS;
+        }
+
+        //check that they are in different packages and method is protected
+        if( class_is_same_package(k_class, referred) ) {
+            return _FALSE;
+        }
+
+        return _TRUE;
+    }
+
+    //check if expected_ref is a super class of 'this', its package differs, and it's protected
+    int vf_TypePool::checkVirtualAccess(SmConstant expected_ref, unsigned short method_idx) {
+        //check if expected_ref is a super class of 'this', its package differs
+        int sp;
+        if( (sp = checkSuperAndPackage(expected_ref)) != _TRUE ) {
+            return sp;
+        }
+
+        //check further
+        //check that they are in different packages and method is protected
+        method_handler method = class_resolve_method(k_class, method_idx);
+
+        if (!method || method_is_static(method)) {
+            //it's not a VerifyError
+            return _FALSE;
+        }
+        
+        // for arrays function clone is public
+        return !method_is_protected(method) ? _FALSE : !memcmp(method_get_name(method), "clone", 6) ? _CLONE : _TRUE;
+    }
+
+    //check if expected_ref is a super class of 'this', its package differs, and it's protected
+    int vf_TypePool::checkFieldAccess(SmConstant expected_ref, unsigned short field_idx) {
+        //check if expected_ref is a super class of 'this', its package differs
+        int sp;
+        if( (sp = checkSuperAndPackage(expected_ref)) != _TRUE ) {
+            return sp;
+        }
+
+        //check further
+        //check that they are in different packages and method is protected
+        field_handler field = class_resolve_nonstatic_field(k_class, field_idx);
+
+        if (!field) {
+            //it's not a VerifyError
+            return _FALSE;
+        }
+        
+        // for arrays function clone is public
+        return field_is_protected(field) ? _TRUE : _FALSE;
+    }
+
+
     void vf_TypePool::NewConstraint(const char *available,
         const char *required)
     {

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h?view=diff&rev=563013&r1=563012&r2=563013
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h Sun Aug  5 20:01:52 2007
@@ -234,6 +234,11 @@
             return SM_BOGUS;
         }
 
+        //check if expected_ref is a super class of 'this', its package differs, and it's protected
+        enum FieldAndMethodCheck {_FALSE, _CLONE, _BOGUS, _TRUE};
+        int checkFieldAccess(SmConstant expected_ref, unsigned short method_idx);
+        int checkVirtualAccess(SmConstant expected_ref, unsigned short method_idx);
+        int checkSuperAndPackage(SmConstant expected_ref);
     private:
         //ref to the main class of the verifier
         vf_Context_t *context;