/* * Unwrap a primitive data type, if necessary. * * If "returnType" is not primitive, we just tuck "value" into JValue and * return it after verifying that it's the right type of object. * * Fails if the field is primitive and "value" is either not a boxed * primitive or is of a type that cannot be converted. * * Returns "true" on success, "false" on failure. */ bool dvmUnboxPrimitive(Object* value, ClassObject* returnType, JValue* pResult) { PrimitiveType typeIndex = returnType->primitiveType; PrimitiveType valueIndex; if (typeIndex == PRIM_NOT) { if (value != NULL && !dvmInstanceof(value->clazz, returnType)) { ALOGD("wrong object type: %s %s", value->clazz->descriptor, returnType->descriptor); return false; } pResult->l = value; return true; } else if (typeIndex == PRIM_VOID) { /* can't put anything into a void */ return false; } valueIndex = getBoxedType((DataObject*)value); if (valueIndex == PRIM_NOT) return false; /* assumes value is stored in first instance field of "value" */ /* (see dvmValidateBoxClasses) */ if (dvmConvertPrimitiveValue(valueIndex, typeIndex, (s4*) ((DataObject*)value)->instanceData, (s4*)pResult) < 0) { ALOGV("Prim conversion failed"); return false; } return true; }
/* * Convert types and widen primitives. Puts the value of "arg" into * "destPtr". * * Returns the width of the argument in 32-bit words (1 or 2), or -1 on error. */ int dvmConvertArgument(DataObject* arg, ClassObject* type, s4* destPtr) { int retVal; if (dvmIsPrimitiveClass(type)) { /* e.g.: "arg" is java/lang/Float instance, "type" is VM float class */ PrimitiveType srcType; s4* valuePtr; srcType = getBoxedType(arg); if (srcType == PRIM_NOT) { // didn't pass a boxed primitive in LOGVV("conv arg: type '%s' not boxed primitive", arg->clazz->descriptor); return -1; } /* assumes value is stored in first instance field */ valuePtr = (s4*) arg->instanceData; retVal = dvmConvertPrimitiveValue(srcType, type->primitiveType, valuePtr, destPtr); } else { /* verify object is compatible */ if ((arg == NULL) || dvmInstanceof(arg->clazz, type)) { *destPtr = (s4) arg; retVal = 1; } else { LOGVV("Arg %p (%s) not compatible with %s", arg, arg->clazz->descriptor, type->descriptor); retVal = -1; } } return retVal; }
/* * Primitive field setters, e.g.: * private void setIField(Object o, Class declaringClass, * Class type, int slot, boolean noAccessCheck, int type_no, int value) * * The "type_no" is defined by the java.lang.reflect.Field class. */ static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] Object* obj = (Object*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ClassObject* fieldType = (ClassObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); int typeNum = args[6]; const s4* valuePtr = (s4*) &args[7]; PrimitiveType srcType = convPrimType(typeNum); JValue* fieldPtr; JValue value; if (!dvmIsPrimitiveClass(fieldType)) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "not a primitive field"); RETURN_VOID(); } /* convert the 32/64-bit arg to a JValue matching the field type */ if (dvmConvertPrimitiveValue(srcType, fieldType->primitiveType, valuePtr, &(value.i)) < 0) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "invalid primitive conversion"); RETURN_VOID(); } /* get a pointer to the field's data; performs access checks */ fieldPtr = getFieldDataAddr(obj, declaringClass, slot, true, noAccessCheck); if (fieldPtr == NULL) RETURN_VOID(); /* store 4 or 8 bytes */ if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { fieldPtr->j = value.j; } else { fieldPtr->i = value.i; } RETURN_VOID(); }
/* * Primitive field getters, e.g.: * private double getIField(Object o, Class declaringClass, * Class type, int slot, boolean noAccessCheck, int type_no) * * The "type_no" is defined by the java.lang.reflect.Field class. */ static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] Object* obj = (Object*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ClassObject* fieldType = (ClassObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); int typeNum = args[6]; PrimitiveType targetType = convPrimType(typeNum); const JValue* fieldPtr; JValue value; if (!dvmIsPrimitiveClass(fieldType)) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "not a primitive field"); RETURN_VOID(); } /* get a pointer to the field's data; performs access checks */ fieldPtr = getFieldDataAddr(obj, declaringClass, slot, false,noAccessCheck); if (fieldPtr == NULL) RETURN_VOID(); /* copy 4 or 8 bytes out */ if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { value.j = fieldPtr->j; } else { value.i = fieldPtr->i; } /* retrieve value, performing a widening conversion if necessary */ if (dvmConvertPrimitiveValue(fieldType->primitiveType, targetType, &(value.i), &(pResult->i)) < 0) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "invalid primitive conversion"); RETURN_VOID(); } }
/* * Primitive field setters, e.g.: * private void setIField(Object o, Class declaringClass, * Class type, int slot, boolean noAccessCheck, int type_no, int value) * * The "type_no" is defined by the java.lang.reflect.Field class. */ static void Dalvik_java_lang_reflect_Field_setPrimitiveField(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] Object* obj = (Object*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ClassObject* fieldType = (ClassObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); int typeNum = args[6]; const s4* valuePtr = (s4*) &args[7]; #ifdef WITH_TAINT_TRACKING /* rtaint = args[8] * thisPtr taint = args[9] * obj taint = args[10] * declaringClass taint = args[11] * fieldType taint = args[12] * slot taint = args[13] * noAccessCheck taint = args[14] * typeNum taint = args[15] */ u4 valueTaint = args[16]; #endif PrimitiveType srcType = convPrimType(typeNum); JValue* fieldPtr; JValue value; if (!dvmIsPrimitiveClass(fieldType)) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "not a primitive field"); RETURN_VOID(); } /* convert the 32/64-bit arg to a JValue matching the field type */ if (dvmConvertPrimitiveValue(srcType, fieldType->primitiveType, valuePtr, &(value.i)) < 0) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "invalid primitive conversion"); RETURN_VOID(); } /* get a pointer to the field's data; performs access checks */ fieldPtr = getFieldDataAddr(obj, declaringClass, slot, true, noAccessCheck); if (fieldPtr == NULL) RETURN_VOID(); /* store 4 or 8 bytes */ if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { fieldPtr->j = value.j; } else { fieldPtr->i = value.i; } #ifdef WITH_TAINT_TRACKING /* If we got this far, we know the fields is okay to access and there * will not be a problem getting the field from the slot */ { Field* field = dvmSlotToField(declaringClass, slot); assert(field != NULL); if (dvmIsStaticField(field)) { StaticField* sfield = (StaticField*)field; dvmSetStaticFieldTaint(sfield, valueTaint); } else { /* Note, getFieldDataAddr() already checked that * obj is of type declaringClass, so no need to check here */ InstField* ifield = (InstField*)field; if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { dvmSetFieldTaintWide(obj, ifield->byteOffset, valueTaint); } else { dvmSetFieldTaint(obj, ifield->byteOffset, valueTaint); } } } #endif RETURN_VOID(); }
/* * Primitive field getters, e.g.: * private double getIField(Object o, Class declaringClass, * Class type, int slot, boolean noAccessCheck, int type_no) * * The "type_no" is defined by the java.lang.reflect.Field class. */ static void Dalvik_java_lang_reflect_Field_getPrimitiveField(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] Object* obj = (Object*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ClassObject* fieldType = (ClassObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); int typeNum = args[6]; #ifdef WITH_TAINT_TRACKING u4* rtaint = (u4*) &args[7]; /* return taint tag slot */ #endif PrimitiveType targetType = convPrimType(typeNum); const JValue* fieldPtr; JValue value; if (!dvmIsPrimitiveClass(fieldType)) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "not a primitive field"); RETURN_VOID(); } /* get a pointer to the field's data; performs access checks */ fieldPtr = getFieldDataAddr(obj, declaringClass, slot, false,noAccessCheck); if (fieldPtr == NULL) RETURN_VOID(); /* copy 4 or 8 bytes out */ if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { value.j = fieldPtr->j; } else { value.i = fieldPtr->i; } /* retrieve value, performing a widening conversion if necessary */ if (dvmConvertPrimitiveValue(fieldType->primitiveType, targetType, &(value.i), &(pResult->i)) < 0) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "invalid primitive conversion"); RETURN_VOID(); } #ifdef WITH_TAINT_TRACKING /* If we got this far, we know the fields is okay to access and there * will not be a problem getting the field from the slot */ { Field* field = dvmSlotToField(declaringClass, slot); assert(field != NULL); if (dvmIsStaticField(field)) { StaticField* sfield = (StaticField*)field; *rtaint = dvmGetStaticFieldTaint(sfield); } else { /* Note, getFieldDataAddr() already checked that * obj is of type declaringClass, so no need to check here */ InstField* ifield = (InstField*)field; if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { *rtaint = dvmGetFieldTaintWide(obj, ifield->byteOffset); } else { *rtaint = dvmGetFieldTaint(obj, ifield->byteOffset); } } } #endif }