static void checkMergeTab(void);
static bool isInitMethod(const Method* meth);
static RegType getInvocationThis(const RegType* insnRegs,\
- const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay);
+ const int insnRegCount, const DecodedInstruction* pDecInsn,
+ VerifyError* pFailure);
static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
- u4 vsrc, RegType checkType, bool* pOkay);
+ u4 vsrc, RegType checkType, VerifyError* pFailure);
static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\
RegisterTable* regTable, UninitInstanceMap* uninitMap);
static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
/*
* Look up a class reference given as a simple string descriptor.
+ *
+ * If we can't find it, return a generic substitute when possible.
*/
static ClassObject* lookupClassByDescriptor(const Method* meth,
- const char* pDescriptor, bool* pOkay)
+ const char* pDescriptor, VerifyError* pFailure)
{
/*
* The javac compiler occasionally puts references to nonexistent
if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
LOG_VFY("VFY: invalid char in signature in '%s'\n",
pDescriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
/*
} else {
/* We are looking at a primitive type. */
LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
if (clazz == NULL) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
}
if (dvmIsPrimitiveClass(clazz)) {
LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
clazz = NULL;
}
* NOTE: this is also expected to verify the signature.
*/
static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
- bool* pOkay)
+ VerifyError* pFailure)
{
const char* sig = *pSig;
const char* endp = sig;
;
if (*endp != ';') {
LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return NULL;
}
*pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
- return lookupClassByDescriptor(meth, typeStr, pOkay);
+ return lookupClassByDescriptor(meth, typeStr, pFailure);
}
/*
* NOTE: this is also expected to verify the signature.
*/
static ClassObject* lookupSignatureArrayClass(const Method* meth,
- const char** pSig, bool* pOkay)
+ const char** pSig, VerifyError* pFailure)
{
const char* sig = *pSig;
const char* endp = sig;
;
if (*endp != ';') {
LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return NULL;
}
}
*pSig = endp;
- return lookupClassByDescriptor(meth, typeStr, pOkay);
+ return lookupClassByDescriptor(meth, typeStr, pFailure);
}
/*
{
DexParameterIterator iterator;
int actualArgs, expectedArgs, argStart;
- bool okay = true;
+ VerifyError failure = VERIFY_ERROR_NONE;
dexParameterIteratorInit(&iterator, &meth->prototype);
argStart = meth->registersSize - meth->insSize;
*/
{
ClassObject* clazz =
- lookupClassByDescriptor(meth, descriptor, &okay);
- if (!okay)
+ lookupClassByDescriptor(meth, descriptor, &failure);
+ if (!VERIFY_OK(failure))
goto bad_sig;
regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
}
case 'L':
case '[':
{
- bool okay = true;
+ VerifyError failure = VERIFY_ERROR_NONE;
ClassObject* clazz =
- lookupClassByDescriptor(meth, descriptor, &okay);
- assert(okay);
+ lookupClassByDescriptor(meth, descriptor, &failure);
+ assert(VERIFY_OK(failure));
type = regTypeFromClass(clazz);
}
break;
* Widening conversions on integers and references are allowed, but
* narrowing conversions are not.
*
- * Returns the resolved method on success, NULL (and sets "*pOkay" to "false")
- * on failure.
+ * Returns the resolved method on success, NULL on failure (with *pFailure
+ * set appropriately).
*/
static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
const int insnRegCount, const DecodedInstruction* pDecInsn,
UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
- bool isSuper, bool* pOkay)
+ bool isSuper, VerifyError* pFailure)
{
Method* resMethod;
char* sigOriginal = NULL;
if (methodType == METHOD_INTERFACE) {
resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
} else {
- resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
+ resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType,
+ pFailure);
}
if (resMethod == NULL) {
/* failed; print a meaningful failure message */
dvmMethodTypeStr(methodType), pDecInsn->vB,
classDescriptor, methodName, methodDesc);
free(methodDesc);
+ *pFailure = VERIFY_ERROR_NO_METHOD;
goto fail;
}
(super == NULL) ? "-" : super->descriptor,
resMethod->name, desc);
free(desc);
+ *pFailure = VERIFY_ERROR_NO_METHOD;
goto fail;
}
}
RegType actualArgType;
actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
- pOkay);
- if (!*pOkay)
+ pFailure);
+ if (!VERIFY_OK(*pFailure))
goto fail;
if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
switch (*sig) {
case 'L':
{
- ClassObject* clazz = lookupSignatureClass(meth, &sig, pOkay);
- if (!*pOkay)
+ ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure);
+ if (!VERIFY_OK(*pFailure))
goto bad_sig;
verifyRegisterType(insnRegs, insnRegCount, getReg,
- regTypeFromClass(clazz), pOkay);
- if (!*pOkay) {
+ regTypeFromClass(clazz), pFailure);
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: bad arg %d (into %s)\n",
actualArgs, clazz->descriptor);
goto bad_sig;
case '[':
{
ClassObject* clazz =
- lookupSignatureArrayClass(meth, &sig, pOkay);
- if (!*pOkay)
+ lookupSignatureArrayClass(meth, &sig, pFailure);
+ if (!VERIFY_OK(*pFailure))
goto bad_sig;
verifyRegisterType(insnRegs, insnRegCount, getReg,
- regTypeFromClass(clazz), pOkay);
- if (!*pOkay) {
+ regTypeFromClass(clazz), pFailure);
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: bad arg %d (into %s)\n",
actualArgs, clazz->descriptor);
goto bad_sig;
break;
case 'Z':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeBoolean, pOkay);
+ kRegTypeBoolean, pFailure);
actualArgs++;
break;
case 'C':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeChar, pOkay);
+ kRegTypeChar, pFailure);
actualArgs++;
break;
case 'B':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeByte, pOkay);
+ kRegTypeByte, pFailure);
actualArgs++;
break;
case 'I':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeInteger, pOkay);
+ kRegTypeInteger, pFailure);
actualArgs++;
break;
case 'S':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeShort, pOkay);
+ kRegTypeShort, pFailure);
actualArgs++;
break;
case 'F':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeFloat, pOkay);
+ kRegTypeFloat, pFailure);
actualArgs++;
break;
case 'D':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeDoubleLo, pOkay);
+ kRegTypeDoubleLo, pFailure);
actualArgs += 2;
break;
case 'J':
verifyRegisterType(insnRegs, insnRegCount, getReg,
- kRegTypeLongLo, pOkay);
+ kRegTypeLongLo, pFailure);
actualArgs += 2;
break;
default:
if (resMethod != NULL) {
char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
LOG_VFY("VFY: rejecting call to %s.%s %s\n",
- resMethod->clazz->descriptor, resMethod->name, desc);
+ resMethod->clazz->descriptor, resMethod->name, desc);
free(desc);
}
fail:
free(sigOriginal);
- *pOkay = false;
+ if (*pFailure == VERIFY_ERROR_NONE)
+ *pFailure = VERIFY_ERROR_GENERIC;
return NULL;
}
/*
* Get the type of register N, verifying that the register is valid.
*
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" appropriately if the register number is out of range.
*/
static inline RegType getRegisterType(const RegType* insnRegs,
- const int insnRegCount, u4 vsrc, bool* pOkay)
+ const int insnRegCount, u4 vsrc, VerifyError* pFailure)
{
RegType type;
if (vsrc >= (u4) insnRegCount) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return kRegTypeUnknown;
} else {
return insnRegs[vsrc];
/*
* Get the value from a register, and cast it to a ClassObject. Sets
- * "pOkay" to false if something fails.
+ * "*pFailure" if something fails.
*
* This fails if the register holds an uninitialized class.
*
* If the register holds kRegTypeZero, this returns a NULL pointer.
*/
static ClassObject* getClassFromRegister(const RegType* insnRegs,
- const int insnRegCount, u4 vsrc, bool* pOkay)
+ const int insnRegCount, u4 vsrc, VerifyError* pFailure)
{
ClassObject* clazz = NULL;
RegType type;
/* get the element type of the array held in vsrc */
- type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
- if (!*pOkay)
+ type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+ if (!VERIFY_OK(*pFailure))
goto bail;
/* if "always zero", we allow it to fail at runtime */
if (!regTypeIsReference(type)) {
LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
vsrc, type);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
if (regTypeIsUninitReference(type)) {
LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
* and then return vC.
*/
static RegType getInvocationThis(const RegType* insnRegs,
- const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay)
+ const int insnRegCount, const DecodedInstruction* pDecInsn,
+ VerifyError* pFailure)
{
RegType thisType = kRegTypeUnknown;
if (pDecInsn->vA < 1) {
LOG_VFY("VFY: invoke lacks 'this'\n");
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
/* get the element type of the array held in vsrc */
- thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pOkay);
- if (!*pOkay) {
- LOG_VFY("VFY: failed to get this from register %u\n", pDecInsn->vC);
+ thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure);
+ if (!VERIFY_OK(*pFailure)) {
+ LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC);
goto bail;
}
if (!regTypeIsReference(thisType)) {
LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
pDecInsn->vC, thisType);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
* "newType" is the "Lo" part of a 64-bit value, register N+1 will be
* set to "newType+1".
*
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" if the register number is out of range.
*/
static void setRegisterType(RegType* insnRegs, const int insnRegCount,
- u4 vdst, RegType newType, bool* pOkay)
+ u4 vdst, RegType newType, VerifyError* pFailure)
{
//LOGD("set-reg v%u = %d\n", vdst, newType);
switch (newType) {
case kRegTypeFloat:
case kRegTypeZero:
if (vdst >= (u4) insnRegCount) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
} else {
insnRegs[vdst] = newType;
}
case kRegTypeLongLo:
case kRegTypeDoubleLo:
if (vdst+1 >= (u4) insnRegCount) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
} else {
insnRegs[vdst] = newType;
insnRegs[vdst+1] = newType+1;
case kRegTypeLongHi:
case kRegTypeDoubleHi:
/* should never set these explicitly */
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
case kRegTypeUninit:
default:
if (regTypeIsReference(newType)) {
if (vdst >= (u4) insnRegCount) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
insnRegs[vdst] = newType;
case kRegTypeConflict: // should only be set during a merge
LOG_VFY("Unexpected set type %d\n", newType);
assert(false);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
}
* interface, verify that the register implements checkType.
*/
static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
- u4 vsrc, RegType checkType, bool* pOkay)
+ u4 vsrc, RegType checkType, VerifyError* pFailure)
{
if (vsrc >= (u4) insnRegCount) {
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return;
}
if (!canConvertTo1nr(srcType, checkType)) {
LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
vsrc, srcType, checkType);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
break;
case kRegTypeLongLo:
if (vsrc+1 >= (u4) insnRegCount) {
LOG_VFY("VFY: register2 v%u out of range (%d)\n",
vsrc, insnRegCount);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
} else if (insnRegs[vsrc+1] != srcType+1) {
LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
} else if (!canConvertTo2(srcType, checkType)) {
LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
vsrc, srcType, checkType);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
break;
case kRegTypeConflict:
/* should never be checking for these explicitly */
assert(false);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return;
case kRegTypeUninit:
default:
if (!regTypeIsReference(checkType)) {
LOG_VFY("VFY: unexpected check type %d\n", checkType);
assert(false);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
if (regTypeIsUninitReference(checkType)) {
LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
/* make sure srcType is initialized reference or always-NULL */
if (!regTypeIsReference(srcType)) {
LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
if (regTypeIsUninitReference(srcType)) {
LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
/* if the register isn't Zero, make sure it's an instance of check */
{
LOG_VFY("VFY: %s does not implement %s\n",
srcClass->descriptor, checkClass->descriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
*/
} else {
if (!dvmInstanceof(srcClass, checkClass)) {
LOG_VFY("VFY: %s is not instance of %s\n",
srcClass->descriptor, checkClass->descriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
}
}
* "insnRegCount" to encompass the result register.
*/
static void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
- RegType newType, bool* pOkay)
+ RegType newType, VerifyError* pFailure)
{
setRegisterType(insnRegs, insnRegCount + kExtraRegs,
- RESULT_REGISTER(insnRegCount), newType, pOkay);
+ RESULT_REGISTER(insnRegCount), newType, pFailure);
}
* must be marked as initialized.
*/
static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
- UninitInstanceMap* uninitMap, RegType uninitType, bool* pOkay)
+ UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure)
{
ClassObject* clazz;
RegType initType;
if (clazz == NULL) {
LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
uninitType, regTypeToUninitIndex(uninitType));
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
return;
}
initType = regTypeFromClass(clazz);
*
* For category 2 values, "type" must be the "low" half of the value.
*
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if something looks wrong.
*/
-static void checkTypeCategory(RegType type, TypeCategory cat, bool* pOkay)
+static void checkTypeCategory(RegType type, TypeCategory cat,
+ VerifyError* pFailure)
{
switch (cat) {
case kTypeCategory1nr:
case kRegTypeInteger:
break;
default:
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
break;
case kRegTypeDoubleLo:
break;
default:
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
break;
case kTypeCategoryRef:
if (type != kRegTypeZero && !regTypeIsReference(type))
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
default:
assert(false);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
break;
}
}
* Does not verify that "typel" is in fact the low part of a 64-bit
* register pair.
*/
-static void checkWidePair(RegType typel, RegType typeh, bool* pOkay)
+static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure)
{
if ((typeh != typel+1))
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
/*
* "vsrc" values are checked against this.
*/
static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
- u4 vsrc, TypeCategory cat, bool* pOkay)
+ u4 vsrc, TypeCategory cat, VerifyError* pFailure)
{
- RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
- if (*pOkay)
- checkTypeCategory(type, cat, pOkay);
- if (*pOkay)
- setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+ RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+ if (VERIFY_OK(*pFailure))
+ checkTypeCategory(type, cat, pFailure);
+ if (VERIFY_OK(*pFailure))
+ setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
- if (!*pOkay) {
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
}
}
* "vsrc" to "vdst". This copies both halves of the register.
*/
static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
- u4 vsrc, bool* pOkay)
+ u4 vsrc, VerifyError* pFailure)
{
- RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
- RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pOkay);
- if (*pOkay) {
- checkTypeCategory(typel, kTypeCategory2, pOkay);
- checkWidePair(typel, typeh, pOkay);
+ RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+ RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure);
+ if (VERIFY_OK(*pFailure)) {
+ checkTypeCategory(typel, kTypeCategory2, pFailure);
+ checkWidePair(typel, typeh, pFailure);
}
- if (*pOkay)
- setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+ if (VERIFY_OK(*pFailure))
+ setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
- if (!*pOkay) {
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
}
}
* because that would affect the test on "vdst" as well.
*/
static void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
- u4 vdst, TypeCategory cat, bool* pOkay)
+ u4 vdst, TypeCategory cat, VerifyError* pFailure)
{
RegType type;
u4 vsrc;
vsrc = RESULT_REGISTER(insnRegCount);
- type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
- if (*pOkay)
- checkTypeCategory(type, cat, pOkay);
- if (*pOkay) {
- setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+ type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure);
+ if (VERIFY_OK(*pFailure))
+ checkTypeCategory(type, cat, pFailure);
+ if (VERIFY_OK(*pFailure)) {
+ setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
insnRegs[vsrc] = kRegTypeUnknown;
}
- if (!*pOkay) {
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
vdst, vsrc, cat, type);
}
* because that would affect the test on "vdst" as well.
*/
static void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
- u4 vdst, bool* pOkay)
+ u4 vdst, VerifyError* pFailure)
{
RegType typel, typeh;
u4 vsrc;
vsrc = RESULT_REGISTER(insnRegCount);
- typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
- typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1, pOkay);
- if (*pOkay) {
- checkTypeCategory(typel, kTypeCategory2, pOkay);
- checkWidePair(typel, typeh, pOkay);
+ typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc,
+ pFailure);
+ typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1,
+ pFailure);
+ if (VERIFY_OK(*pFailure)) {
+ checkTypeCategory(typel, kTypeCategory2, pFailure);
+ checkWidePair(typel, typeh, pFailure);
}
- if (*pOkay) {
- setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+ if (VERIFY_OK(*pFailure)) {
+ setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
insnRegs[vsrc] = kRegTypeUnknown;
insnRegs[vsrc+1] = kRegTypeUnknown;
}
- if (!*pOkay) {
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
vdst, vsrc, typel, typeh);
}
*/
static void checkUnop(RegType* insnRegs, const int insnRegCount,
DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
- bool* pOkay)
+ VerifyError* pFailure)
{
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
- setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+ setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
}
/*
*/
static void checkLitop(RegType* insnRegs, const int insnRegCount,
DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
- bool checkBooleanOp, bool* pOkay)
+ bool checkBooleanOp, VerifyError* pFailure)
{
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
- if (*pOkay && checkBooleanOp) {
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+ if (VERIFY_OK(*pFailure) && checkBooleanOp) {
assert(dstType == kRegTypeInteger);
/* check vB with the call, then check the constant manually */
if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
dstType = kRegTypeBoolean;
}
}
- setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+ setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
}
/*
*/
static void checkBinop(RegType* insnRegs, const int insnRegCount,
DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
- RegType srcType2, bool checkBooleanOp, bool* pOkay)
+ RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
{
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1, pOkay);
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2, pOkay);
- if (*pOkay && checkBooleanOp) {
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1,
+ pFailure);
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2,
+ pFailure);
+ if (VERIFY_OK(*pFailure) && checkBooleanOp) {
assert(dstType == kRegTypeInteger);
if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
dstType = kRegTypeBoolean;
}
- setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+ setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
}
/*
*/
static void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
- RegType srcType2, bool checkBooleanOp, bool* pOkay)
+ RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
{
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1, pOkay);
- verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2, pOkay);
- if (*pOkay && checkBooleanOp) {
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1,
+ pFailure);
+ verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2,
+ pFailure);
+ if (VERIFY_OK(*pFailure) && checkBooleanOp) {
assert(dstType == kRegTypeInteger);
if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
dstType = kRegTypeBoolean;
}
- setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+ setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
}
* allow it to be uninitialized if this is an "<init>" method and the field
* is declared within the "objType" class.
*
- * Returns an InstField on success, returns NULL and sets "*pOkay" to false
+ * Returns an InstField on success, returns NULL and sets "*pFailure"
* on failure.
*/
static InstField* getInstField(const Method* meth,
const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
- bool* pOkay)
+ VerifyError* pFailure)
{
InstField* instField = NULL;
ClassObject* objClass;
bool mustBeLocal = false;
if (!regTypeIsReference(objType)) {
- LOG_VFY("VFY: attempt to access field of non-reference type %d\n",
+ LOG_VFY("VFY: attempt to access field in non-reference type %d\n",
objType);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
- instField = dvmOptResolveInstField(meth->clazz, fieldIdx);
+ instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure);
if (instField == NULL) {
LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
- *pOkay = false;
+ assert(!VERIFY_OK(*pFailure));
goto bail;
}
if (regTypeIsUninitReference(objType)) {
if (!isInitMethod(meth) || meth->clazz != objClass) {
LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
mustBeLocal = true;
LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
instField->field.clazz->descriptor, instField->field.name,
objClass->descriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_NO_FIELD;
goto bail;
}
{
LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
instField->field.name, objClass->descriptor);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
goto bail;
}
}
/*
* Look up a static field.
*
- * Returns a StaticField on success, returns NULL and sets "*pOkay" to false
+ * Returns a StaticField on success, returns NULL and sets "*pFailure"
* on failure.
*/
static StaticField* getStaticField(const Method* meth, int fieldIdx,
- bool* pOkay)
+ VerifyError* pFailure)
{
StaticField* staticField;
- staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx);
+ staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure);
if (staticField == NULL) {
DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
const DexFieldId* pFieldId;
LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
dexStringById(pDexFile, pFieldId->nameIdx),
dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
-
- *pOkay = false;
+ assert(!VERIFY_OK(*pFailure));
goto bail;
}
* If "field" is marked "final", make sure this is the either <clinit>
* or <init> as appropriate.
*
- * Sets "*pOkay" to false on failure.
+ * Sets "*pFailure" on failure.
*/
static void checkFinalFieldAccess(const Method* meth, const Field* field,
- bool* pOkay)
+ VerifyError* pFailure)
{
if (!dvmIsFinalField(field))
return;
if (meth->clazz != field->clazz) {
LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
field->clazz->descriptor, field->name);
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_ACCESS;
return;
}
/*
- * The EMMA code coverage tool generates a static method that
- * modifies a private static final field. The method is only
- * called by <clinit>, so the code is reasonable if not quite
- * kosher. (Attempting to *compile* code that does something
- * like that will earn you a quick thumbs-down from javac.)
- *
- * The verifier in another popular VM doesn't complain about this,
- * so we're going to allow classes to modify their own static
- * final fields outside of class initializers. Further testing
- * showed that modifications to instance fields are also allowed.
+ * The VM spec descriptions of putfield and putstatic say that
+ * IllegalAccessError is only thrown when the instructions appear
+ * outside the declaring class. Our earlier attempts to restrict
+ * final field modification to constructors are, therefore, wrong.
*/
#if 0
/* make sure we're in the right kind of constructor */
if (!isClassInitMethod(meth)) {
LOG_VFY_METH(meth,
"VFY: can't modify final static field outside <clinit>\n");
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
} else {
if (!isInitMethod(meth)) {
LOG_VFY_METH(meth,
"VFY: can't modify final field outside <init>\n");
- *pOkay = false;
+ *pFailure = VERIFY_ERROR_GENERIC;
}
}
#endif
/*
* Make sure that the register type is suitable for use as an array index.
*
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if not.
*/
static void checkArrayIndexType(const Method* meth, RegType regType,
- bool* pOkay)
+ VerifyError* pFailure)
{
- if (*pOkay) {
+ if (VERIFY_OK(*pFailure)) {
/*
* The 1nr types are interchangeable at this level. We could
* do something special if we can definitively identify it as a
* float, but there's no real value in doing so.
*/
- checkTypeCategory(regType, kTypeCategory1nr, pOkay);
- if (!*pOkay) {
+ checkTypeCategory(regType, kTypeCategory1nr, pFailure);
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
regType);
}
* Returns NULL if no matching exception handler can be found, or if the
* exception is not a subclass of Throwable.
*/
-static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx)
+static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
+ VerifyError* pFailure)
{
+ VerifyError localFailure;
const DexCode* pCode;
DexFile* pDexFile;
ClassObject* commonSuper = NULL;
+ bool foundPossibleHandler = false;
u4 handlersSize;
u4 offset;
u4 i;
if (handler->address == (u4) insnIdx) {
ClassObject* clazz;
+ foundPossibleHandler = true;
if (handler->typeIdx == kDexNoIndex)
clazz = gDvm.classJavaLangThrowable;
else
- clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx);
+ clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
+ &localFailure);
if (clazz == NULL) {
LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
handler->typeIdx,
dexStringByTypeIdx(pDexFile, handler->typeIdx));
+ /* TODO: do we want to keep going? If we don't fail
+ * this we run the risk of having a non-Throwable
+ * introduced at runtime. However, that won't pass
+ * an instanceof test, so is essentially harmless. */
} else {
if (commonSuper == NULL)
commonSuper = clazz;
}
if (commonSuper == NULL) {
+ /* no catch blocks, or no catches with classes we can find */
LOG_VFY_METH(meth,
"VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
+ *pFailure = VERIFY_ERROR_GENERIC;
+ } else {
+ // TODO: verify the class is an instance of Throwable?
}
return commonSuper;
static void verifyFilledNewArrayRegs(const Method* meth,
const RegType* insnRegs, const int insnRegCount,
const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
- bool* pOkay)
+ VerifyError* pFailure)
{
u4 argCount = pDecInsn->vA;
RegType expectedType;
else
getReg = pDecInsn->arg[ui];
- verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType, pOkay);
- if (!*pOkay) {
+ verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType,
+ pFailure);
+ if (!VERIFY_OK(*pFailure)) {
LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
return;
}
RegType tmpType;
DecodedInstruction decInsn;
bool justSetResult = false;
- bool okay = true;
+ VerifyError failure = VERIFY_ERROR_NONE;
#ifndef NDEBUG
memset(&decInsn, 0x81, sizeof(decInsn));
*/
if (decInsn.vA != 0) {
LOG_VFY("VFY: encountered data table in instruction stream\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
}
break;
case OP_MOVE_FROM16:
case OP_MOVE_16:
copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
- kTypeCategory1nr, &okay);
+ kTypeCategory1nr, &failure);
break;
case OP_MOVE_WIDE:
case OP_MOVE_WIDE_FROM16:
case OP_MOVE_WIDE_16:
- copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &okay);
+ copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure);
break;
case OP_MOVE_OBJECT:
case OP_MOVE_OBJECT_FROM16:
case OP_MOVE_OBJECT_16:
copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
- kTypeCategoryRef, &okay);
+ kTypeCategoryRef, &failure);
break;
/*
*/
case OP_MOVE_RESULT:
copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
- kTypeCategory1nr, &okay);
+ kTypeCategory1nr, &failure);
break;
case OP_MOVE_RESULT_WIDE:
- copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &okay);
+ copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure);
break;
case OP_MOVE_RESULT_OBJECT:
copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
- kTypeCategoryRef, &okay);
+ kTypeCategoryRef, &failure);
break;
case OP_MOVE_EXCEPTION:
* "resClass" will hold the closest common superclass of all
* exceptions that can be handled here.
*/
- resClass = getCaughtExceptionType(meth, insnIdx);
+ resClass = getCaughtExceptionType(meth, insnIdx, &failure);
if (resClass == NULL) {
- okay = false;
+ assert(!VERIFY_OK(failure));
} else {
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(resClass), &okay);
+ regTypeFromClass(resClass), &failure);
}
break;
case OP_RETURN_VOID:
- okay = checkConstructorReturn(meth, workRegs, insnRegCount);
- if (okay && getMethodReturnType(meth) != kRegTypeUnknown) {
+ if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+ failure = VERIFY_ERROR_GENERIC;
+ } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
LOG_VFY("VFY: return-void not expected\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
}
break;
case OP_RETURN:
- okay = checkConstructorReturn(meth, workRegs, insnRegCount);
- if (okay) {
+ if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+ failure = VERIFY_ERROR_GENERIC;
+ } else {
/* check the method signature */
RegType returnType = getMethodReturnType(meth);
- checkTypeCategory(returnType, kTypeCategory1nr, &okay);
- if (!okay)
+ checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure))
LOG_VFY("VFY: return-32 not expected\n");
/* check the register contents */
returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
- checkTypeCategory(returnType, kTypeCategory1nr, &okay);
- if (!okay)
+ &failure);
+ checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure))
LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
}
break;
case OP_RETURN_WIDE:
- okay = checkConstructorReturn(meth, workRegs, insnRegCount);
- if (okay) {
+ if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+ failure = VERIFY_ERROR_GENERIC;
+ } else {
RegType returnType, returnTypeHi;
/* check the method signature */
returnType = getMethodReturnType(meth);
- checkTypeCategory(returnType, kTypeCategory2, &okay);
- if (!okay)
+ checkTypeCategory(returnType, kTypeCategory2, &failure);
+ if (!VERIFY_OK(failure))
LOG_VFY("VFY: return-wide not expected\n");
/* check the register contents */
returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
+ &failure);
returnTypeHi = getRegisterType(workRegs, insnRegCount,
- decInsn.vA +1, &okay);
- if (okay) {
- checkTypeCategory(returnType, kTypeCategory2, &okay);
- checkWidePair(returnType, returnTypeHi, &okay);
+ decInsn.vA +1, &failure);
+ if (VERIFY_OK(failure)) {
+ checkTypeCategory(returnType, kTypeCategory2, &failure);
+ checkWidePair(returnType, returnTypeHi, &failure);
}
- if (!okay) {
+ if (!VERIFY_OK(failure)) {
LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
decInsn.vA);
}
}
break;
case OP_RETURN_OBJECT:
- okay = checkConstructorReturn(meth, workRegs, insnRegCount);
- if (okay) {
+ if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+ failure = VERIFY_ERROR_GENERIC;
+ } else {
RegType returnType = getMethodReturnType(meth);
- checkTypeCategory(returnType, kTypeCategoryRef, &okay);
- if (!okay) {
+ checkTypeCategory(returnType, kTypeCategoryRef, &failure);
+ if (!VERIFY_OK(failure)) {
LOG_VFY("VFY: return-object not expected\n");
break;
}
declClass = regTypeInitializedReferenceToClass(returnType);
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vA, &okay);
- if (!okay)
+ decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
if (!dvmIsInterfaceClass(declClass) &&
{
LOG_VFY("VFY: returning %s, declared %s\n",
resClass->descriptor, declClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
case OP_CONST:
/* could be boolean, int, float, or a null reference */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dvmDetermineCat1Const((s4)decInsn.vB), &okay);
+ dvmDetermineCat1Const((s4)decInsn.vB), &failure);
break;
case OP_CONST_HIGH16:
/* could be boolean, int, float, or a null reference */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dvmDetermineCat1Const((s4) decInsn.vB << 16), &okay);
+ dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure);
break;
case OP_CONST_WIDE_16:
case OP_CONST_WIDE_32:
case OP_CONST_WIDE_HIGH16:
/* could be long or double; default to long and allow conversion */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- kRegTypeLongLo, &okay);
+ kRegTypeLongLo, &failure);
break;
case OP_CONST_STRING:
case OP_CONST_STRING_JUMBO:
assert(gDvm.classJavaLangString != NULL);
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(gDvm.classJavaLangString), &okay);
+ regTypeFromClass(gDvm.classJavaLangString), &failure);
break;
case OP_CONST_CLASS:
assert(gDvm.classJavaLangClass != NULL);
/* make sure we can resolve the class; access check is important */
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
decInsn.vB, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else {
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(gDvm.classJavaLangClass), &okay);
+ regTypeFromClass(gDvm.classJavaLangClass), &failure);
}
break;
case OP_MONITOR_ENTER:
case OP_MONITOR_EXIT:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (okay && !regTypeIsReference(tmpType)) {
- LOG_VFY("VFY: monitor op on non-object\n");
- okay = false;
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (VERIFY_OK(failure)) {
+ if (!regTypeIsReference(tmpType)) {
+ LOG_VFY("VFY: monitor op on non-object\n");
+ failure = VERIFY_ERROR_GENERIC;
+ }
}
break;
* If it fails, an exception is thrown, which we deal with later
* by ignoring the update to decInsn.vA when branching to a handler.
*/
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
decInsn.vB, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else {
RegType origType;
origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
if (!regTypeIsReference(origType)) {
LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(resClass), &okay);
+ regTypeFromClass(resClass), &failure);
}
break;
case OP_INSTANCE_OF:
/* make sure we're checking a reference type */
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
- if (!okay)
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (!regTypeIsReference(tmpType)) {
LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
/* make sure we can resolve the class; access check is important */
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
decInsn.vC, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else {
/* result is boolean */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- kRegTypeBoolean, &okay);
+ kRegTypeBoolean, &failure);
}
break;
case OP_ARRAY_LENGTH:
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL && !dvmIsArrayClass(resClass)) {
LOG_VFY("VFY: array-length on non-array\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
- &okay);
+ &failure);
break;
case OP_NEW_INSTANCE:
* instructions with a magic "always throw InstantiationError"
* instruction. (Not enough bytes to sub in a method call.)
*/
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
decInsn.vB, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else {
RegType uninitType;
/* add the new uninitialized reference to the register ste */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- uninitType, &okay);
+ uninitType, &failure);
}
break;
case OP_NEW_ARRAY:
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
decInsn.vC, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else if (!dvmIsArrayClass(resClass)) {
LOG_VFY("VFY: new-array on non-array class\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
} else {
/* make sure "size" register is valid type */
verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
- kRegTypeInteger, &okay);
+ kRegTypeInteger, &failure);
/* set register type to array class */
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(resClass), &okay);
+ regTypeFromClass(resClass), &failure);
}
break;
case OP_FILLED_NEW_ARRAY:
case OP_FILLED_NEW_ARRAY_RANGE:
- resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+ resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
if (resClass == NULL) {
const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
dvmLogUnableToResolveClass(badClassDesc, meth);
LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
decInsn.vB, badClassDesc, meth->clazz->descriptor);
- okay = false;
+ assert(failure != VERIFY_ERROR_GENERIC);
} else if (!dvmIsArrayClass(resClass)) {
LOG_VFY("VFY: filled-new-array on non-array class\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
} else {
bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
/* check the arguments to the instruction */
verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
- resClass, isRange, &okay);
+ resClass, isRange, &failure);
/* filled-array result goes into "result" register */
setResultRegisterType(workRegs, insnRegCount,
- regTypeFromClass(resClass), &okay);
+ regTypeFromClass(resClass), &failure);
justSetResult = true;
}
break;
case OP_CMPL_FLOAT:
case OP_CMPG_FLOAT:
verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
- &okay);
+ &failure);
verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
- &okay);
+ &failure);
setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
- &okay);
+ &failure);
break;
case OP_CMPL_DOUBLE:
case OP_CMPG_DOUBLE:
verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
- &okay);
+ &failure);
verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
- &okay);
+ &failure);
setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
- &okay);
+ &failure);
break;
case OP_CMP_LONG:
verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
- &okay);
+ &failure);
verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
- &okay);
+ &failure);
setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
- &okay);
+ &failure);
break;
case OP_THROW:
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vA, &okay);
- if (okay && resClass != NULL) {
+ decInsn.vA, &failure);
+ if (VERIFY_OK(failure) && resClass != NULL) {
if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
}
}
break;
case OP_SPARSE_SWITCH:
/* verify that vAA is an integer, or can be converted to one */
verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
- kRegTypeInteger, &okay);
+ kRegTypeInteger, &failure);
break;
case OP_FILL_ARRAY_DATA:
/* Similar to the verification done for APUT */
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vA, &okay);
- if (!okay)
+ decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
/* resClass can be null if the reg type is Zero */
{
LOG_VFY("VFY: invalid fill-array-data on %s\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
if (arrayData[0] != kArrayDataSignature) {
LOG_VFY("VFY: invalid magic for array-data\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (arrayData[1] != elemWidth) {
LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
arrayData[1], elemWidth);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
}
}
break;
RegType type1, type2;
bool tmpResult;
- type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
- if (!okay)
+ type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
+ &failure);
+ type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB,
+ &failure);
+ if (!VERIFY_OK(failure))
break;
/* both references? */
break;
/* both category-1nr? */
- checkTypeCategory(type1, kTypeCategory1nr, &okay);
- checkTypeCategory(type2, kTypeCategory1nr, &okay);
- if (!okay) {
+ checkTypeCategory(type1, kTypeCategory1nr, &failure);
+ checkTypeCategory(type2, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure)) {
LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
break;
}
case OP_IF_GE:
case OP_IF_GT:
case OP_IF_LE:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (!okay)
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
- if (!okay) {
+ checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure)) {
LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
break;
}
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB,&okay);
- if (!okay)
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
- if (!okay) {
+ checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure)) {
LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
break;
}
break;
case OP_IF_EQZ:
case OP_IF_NEZ:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (!okay)
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
if (regTypeIsReference(tmpType))
break;
- checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
- if (!okay)
+ checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure))
LOG_VFY("VFY: expected cat-1 arg to if\n");
break;
case OP_IF_LTZ:
case OP_IF_GEZ:
case OP_IF_GTZ:
case OP_IF_LEZ:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (!okay)
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
- if (!okay)
+ checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+ if (!VERIFY_OK(failure))
LOG_VFY("VFY: expected cat-1 arg to if\n");
break;
RegType srcType, indexType;
indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, indexType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, indexType, &failure);
+ if (!VERIFY_OK(failure))
break;
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
/* verify the class */
{
LOG_VFY("VFY: invalid aget-1nr target %s\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
" inst type=%d (on %s)\n",
srcType, tmpType, resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- tmpType, &okay);
+ tmpType, &failure);
}
break;
RegType dstType, indexType;
indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, indexType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, indexType, &failure);
+ if (!VERIFY_OK(failure))
break;
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
/* verify the class */
{
LOG_VFY("VFY: invalid aget-wide target %s\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
LOG_VFY("VFY: invalid aget-wide on %s\n",
resClass->descriptor);
dstType = kRegTypeUnknown;
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
} else {
dstType = kRegTypeLongLo;
}
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dstType, &okay);
+ dstType, &failure);
}
break;
RegType dstType, indexType;
indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, indexType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, indexType, &failure);
+ if (!VERIFY_OK(failure))
break;
/* get the class of the array we're pulling an object from */
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
ClassObject* elementClass;
assert(resClass != NULL);
if (!dvmIsArrayClass(resClass)) {
LOG_VFY("VFY: aget-object on non-array class\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
assert(resClass->elementClass != NULL);
} else {
LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
dstType = kRegTypeZero;
}
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dstType, &okay);
+ dstType, &failure);
}
break;
case OP_APUT:
RegType srcType, dstType, indexType;
indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, indexType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, indexType, &failure);
+ if (!VERIFY_OK(failure))
break;
/* make sure the source register has the correct type */
srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
+ &failure);
if (!canConvertTo1nr(srcType, tmpType)) {
LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
srcType, tmpType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
/* resClass can be null if the reg type is Zero */
resClass->elementClass->primitiveType == PRIM_NOT)
{
LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (!checkFieldArrayStore1nr(tmpType, dstType)) {
LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
resClass->descriptor, tmpType, dstType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
break;
case OP_APUT_WIDE:
tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, tmpType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, tmpType, &failure);
+ if (!VERIFY_OK(failure))
break;
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (okay) {
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (VERIFY_OK(failure)) {
RegType typeHi =
- getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
- checkTypeCategory(tmpType, kTypeCategory2, &okay);
- checkWidePair(tmpType, typeHi, &okay);
+ getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+ checkTypeCategory(tmpType, kTypeCategory2, &failure);
+ checkWidePair(tmpType, typeHi, &failure);
}
- if (!okay)
+ if (!VERIFY_OK(failure))
break;
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
- if (!okay)
+ decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
/* verify the class and try to refine "dstType" */
{
LOG_VFY("VFY: invalid aput-wide on %s\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
default:
LOG_VFY("VFY: invalid aput-wide on %s\n",
resClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
break;
case OP_APUT_OBJECT:
tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
- &okay);
- checkArrayIndexType(meth, tmpType, &okay);
- if (!okay)
+ &failure);
+ checkArrayIndexType(meth, tmpType, &failure);
+ if (!VERIFY_OK(failure))
break;
/* get the ref we're storing; Zero is okay, Uninit is not */
resClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vA, &okay);
- if (!okay)
+ decInsn.vA, &failure);
+ if (!VERIFY_OK(failure))
break;
if (resClass != NULL) {
ClassObject* arrayClass;
* null pointer exception).
*/
arrayClass = getClassFromRegister(workRegs, insnRegCount,
- decInsn.vB, &okay);
+ decInsn.vB, &failure);
if (arrayClass != NULL) {
/* see if the array holds a compatible type */
if (!dvmIsArrayClass(arrayClass)) {
LOG_VFY("VFY: invalid aput-object on %s\n",
arrayClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (elementClass->primitiveType != PRIM_NOT) {
LOG_VFY("VFY: invalid aput-object of %s into %s\n",
resClass->descriptor, arrayClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
RegType objType, fieldType;
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
/* make sure the field's type is compatible with expectation */
LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
instField->field.clazz->descriptor,
instField->field.name, tmpType, fieldType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+ setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+ &failure);
}
break;
case OP_IGET_WIDE:
RegType objType;
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
/* check the type, which should be prim */
switch (instField->field.signature[0]) {
instField->field.clazz->descriptor,
instField->field.name);
dstType = kRegTypeUnknown;
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- if (okay) {
+ if (VERIFY_OK(failure)) {
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dstType, &okay);
+ dstType, &failure);
}
}
break;
RegType objType;
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
fieldClass = getFieldClass(meth, &instField->field);
if (fieldClass == NULL) {
/* class not found or primitive type */
LOG_VFY("VFY: unable to recover field class from '%s'\n",
instField->field.signature);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- if (okay) {
+ if (VERIFY_OK(failure)) {
assert(!dvmIsPrimitiveClass(fieldClass));
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(fieldClass), &okay);
+ regTypeFromClass(fieldClass), &failure);
}
}
break;
/* make sure the source register has the correct type */
srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
+ &failure);
if (!canConvertTo1nr(srcType, tmpType)) {
LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
srcType, tmpType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &instField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &instField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
/* get type of field we're storing into */
LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
instField->field.clazz->descriptor,
instField->field.name, tmpType, fieldType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
break;
case OP_IPUT_WIDE:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (okay) {
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (VERIFY_OK(failure)) {
RegType typeHi =
- getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
- checkTypeCategory(tmpType, kTypeCategory2, &okay);
- checkWidePair(tmpType, typeHi, &okay);
+ getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+ checkTypeCategory(tmpType, kTypeCategory2, &failure);
+ checkWidePair(tmpType, typeHi, &failure);
}
- if (okay) {
+ if (VERIFY_OK(failure)) {
ClassObject* fieldClass;
InstField* instField;
RegType objType;
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &instField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &instField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
/* check the type, which should be prim */
LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
instField->field.clazz->descriptor,
instField->field.name);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
RegType objType, valueType;
objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
instField = getInstField(meth, uninitMap, objType, decInsn.vC,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &instField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &instField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
fieldClass = getFieldClass(meth, &instField->field);
if (fieldClass == NULL) {
LOG_VFY("VFY: unable to recover field class from '%s'\n",
instField->field.signature);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
if (!regTypeIsReference(valueType)) {
LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
decInsn.vA, instField->field.name,
fieldClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (valueType != kRegTypeZero) {
if (valueClass == NULL) {
LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
decInsn.vA);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
/* allow if field is any interface or field is base class */
valueClass->descriptor, fieldClass->descriptor,
instField->field.clazz->descriptor,
instField->field.name);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
StaticField* staticField;
RegType fieldType;
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
/*
LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
staticField->field.clazz->descriptor,
staticField->field.name, tmpType, fieldType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+ setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+ &failure);
}
break;
case OP_SGET_WIDE:
StaticField* staticField;
RegType dstType;
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
/* check the type, which should be prim */
switch (staticField->field.signature[0]) {
staticField->field.clazz->descriptor,
staticField->field.name);
dstType = kRegTypeUnknown;
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- if (okay) {
+ if (VERIFY_OK(failure)) {
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- dstType, &okay);
+ dstType, &failure);
}
}
break;
StaticField* staticField;
ClassObject* fieldClass;
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
fieldClass = getFieldClass(meth, &staticField->field);
if (fieldClass == NULL) {
LOG_VFY("VFY: unable to recover field class from '%s'\n",
staticField->field.signature);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (dvmIsPrimitiveClass(fieldClass)) {
LOG_VFY("VFY: attempt to get prim field with sget-object\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
setRegisterType(workRegs, insnRegCount, decInsn.vA,
- regTypeFromClass(fieldClass), &okay);
+ regTypeFromClass(fieldClass), &failure);
}
break;
case OP_SPUT:
/* make sure the source register has the correct type */
srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
+ &failure);
if (!canConvertTo1nr(srcType, tmpType)) {
LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
srcType, tmpType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &staticField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &staticField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
/*
LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
staticField->field.clazz->descriptor,
staticField->field.name, tmpType, fieldType);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
break;
case OP_SPUT_WIDE:
- tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
- if (okay) {
+ tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+ if (VERIFY_OK(failure)) {
RegType typeHi =
- getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
- checkTypeCategory(tmpType, kTypeCategory2, &okay);
- checkWidePair(tmpType, typeHi, &okay);
+ getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+ checkTypeCategory(tmpType, kTypeCategory2, &failure);
+ checkWidePair(tmpType, typeHi, &failure);
}
- if (okay) {
+ if (VERIFY_OK(failure)) {
StaticField* staticField;
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &staticField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &staticField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
/* check the type, which should be prim */
LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
staticField->field.clazz->descriptor,
staticField->field.name);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
StaticField* staticField;
RegType valueType;
- staticField = getStaticField(meth, decInsn.vB, &okay);
- if (!okay)
+ staticField = getStaticField(meth, decInsn.vB, &failure);
+ if (!VERIFY_OK(failure))
break;
- checkFinalFieldAccess(meth, &staticField->field, &okay);
- if (!okay)
+ checkFinalFieldAccess(meth, &staticField->field, &failure);
+ if (!VERIFY_OK(failure))
break;
fieldClass = getFieldClass(meth, &staticField->field);
if (fieldClass == NULL) {
LOG_VFY("VFY: unable to recover field class from '%s'\n",
staticField->field.signature);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
- &okay);
- if (!okay)
+ &failure);
+ if (!VERIFY_OK(failure))
break;
if (!regTypeIsReference(valueType)) {
LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
decInsn.vA, staticField->field.name,
fieldClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (valueType != kRegTypeZero) {
if (valueClass == NULL) {
LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
decInsn.vA);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
/* allow if field is any interface or field is base class */
valueClass->descriptor, fieldClass->descriptor,
staticField->field.clazz->descriptor,
staticField->field.name);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
&decInsn, uninitMap, METHOD_VIRTUAL, isRange,
- isSuper, &okay);
- if (!okay)
+ isSuper, &failure);
+ if (!VERIFY_OK(failure))
break;
returnType = getMethodReturnType(calledMethod);
- setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+ setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
justSetResult = true;
}
break;
isRange = (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
&decInsn, uninitMap, METHOD_DIRECT, isRange,
- false, &okay);
- if (!okay)
+ false, &failure);
+ if (!VERIFY_OK(failure))
break;
/*
if (isInitMethod(calledMethod)) {
RegType thisType;
thisType = getInvocationThis(workRegs, insnRegCount,
- &decInsn, &okay);
- if (!okay)
+ &decInsn, &failure);
+ if (!VERIFY_OK(failure))
break;
/* no null refs allowed (?) */
if (thisType == kRegTypeZero) {
LOG_VFY("VFY: unable to initialize null ref\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
if (thisClass != meth->clazz) {
LOG_VFY("VFY: invoke-direct <init> on super only "
"allowed for 'this' in <init>");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
} else if (calledMethod->clazz != thisClass) {
LOG_VFY("VFY: invoke-direct <init> must be on current "
"class or super\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
/* arg must be an uninitialized reference */
if (!regTypeIsUninitReference(thisType)) {
LOG_VFY("VFY: can only initialize the uninitialized\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
*/
int uidx = regTypeToUninitIndex(thisType);
markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
- thisType, &okay);
- if (!okay)
+ thisType, &failure);
+ if (!VERIFY_OK(failure))
break;
}
returnType = getMethodReturnType(calledMethod);
setResultRegisterType(workRegs, insnRegCount,
- returnType, &okay);
+ returnType, &failure);
justSetResult = true;
}
break;
isRange = (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
&decInsn, uninitMap, METHOD_STATIC, isRange,
- false, &okay);
- if (!okay)
+ false, &failure);
+ if (!VERIFY_OK(failure))
break;
returnType = getMethodReturnType(calledMethod);
- setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+ setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
justSetResult = true;
}
break;
isRange = (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
&decInsn, uninitMap, METHOD_INTERFACE, isRange,
- false, &okay);
- if (!okay)
+ false, &failure);
+ if (!VERIFY_OK(failure))
break;
#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
* interface classes, this might have reduced to Object.
*/
thisType = getInvocationThis(workRegs, insnRegCount,
- &decInsn, &okay);
- if (!okay)
+ &decInsn, &failure);
+ if (!VERIFY_OK(failure))
break;
if (thisType == kRegTypeZero) {
thisClass = regTypeInitializedReferenceToClass(thisType);
if (thisClass == NULL) {
LOG_VFY("VFY: interface call on uninitialized\n");
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
{
LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
absMethod->name, thisClass->descriptor);
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
}
}
* in the abstract method, so we're good.
*/
returnType = getMethodReturnType(absMethod);
- setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+ setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
justSetResult = true;
}
break;
case OP_NEG_INT:
case OP_NOT_INT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, &okay);
+ kRegTypeInteger, kRegTypeInteger, &failure);
break;
case OP_NEG_LONG:
case OP_NOT_LONG:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeLongLo, &okay);
+ kRegTypeLongLo, kRegTypeLongLo, &failure);
break;
case OP_NEG_FLOAT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeFloat, &okay);
+ kRegTypeFloat, kRegTypeFloat, &failure);
break;
case OP_NEG_DOUBLE:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeDoubleLo, &okay);
+ kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
break;
case OP_INT_TO_LONG:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeInteger, &okay);
+ kRegTypeLongLo, kRegTypeInteger, &failure);
break;
case OP_INT_TO_FLOAT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeInteger, &okay);
+ kRegTypeFloat, kRegTypeInteger, &failure);
break;
case OP_INT_TO_DOUBLE:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeInteger, &okay);
+ kRegTypeDoubleLo, kRegTypeInteger, &failure);
break;
case OP_LONG_TO_INT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeLongLo, &okay);
+ kRegTypeInteger, kRegTypeLongLo, &failure);
break;
case OP_LONG_TO_FLOAT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeLongLo, &okay);
+ kRegTypeFloat, kRegTypeLongLo, &failure);
break;
case OP_LONG_TO_DOUBLE:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeLongLo, &okay);
+ kRegTypeDoubleLo, kRegTypeLongLo, &failure);
break;
case OP_FLOAT_TO_INT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeFloat, &okay);
+ kRegTypeInteger, kRegTypeFloat, &failure);
break;
case OP_FLOAT_TO_LONG:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeFloat, &okay);
+ kRegTypeLongLo, kRegTypeFloat, &failure);
break;
case OP_FLOAT_TO_DOUBLE:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeFloat, &okay);
+ kRegTypeDoubleLo, kRegTypeFloat, &failure);
break;
case OP_DOUBLE_TO_INT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeDoubleLo, &okay);
+ kRegTypeInteger, kRegTypeDoubleLo, &failure);
break;
case OP_DOUBLE_TO_LONG:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeDoubleLo, &okay);
+ kRegTypeLongLo, kRegTypeDoubleLo, &failure);
break;
case OP_DOUBLE_TO_FLOAT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeDoubleLo, &okay);
+ kRegTypeFloat, kRegTypeDoubleLo, &failure);
break;
case OP_INT_TO_BYTE:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeByte, kRegTypeInteger, &okay);
+ kRegTypeByte, kRegTypeInteger, &failure);
break;
case OP_INT_TO_CHAR:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeChar, kRegTypeInteger, &okay);
+ kRegTypeChar, kRegTypeInteger, &failure);
break;
case OP_INT_TO_SHORT:
checkUnop(workRegs, insnRegCount, &decInsn,
- kRegTypeShort, kRegTypeInteger, &okay);
+ kRegTypeShort, kRegTypeInteger, &failure);
break;
case OP_ADD_INT:
case OP_SHR_INT:
case OP_USHR_INT:
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+ kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
break;
case OP_AND_INT:
case OP_OR_INT:
case OP_XOR_INT:
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+ kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
break;
case OP_ADD_LONG:
case OP_SUB_LONG:
case OP_OR_LONG:
case OP_XOR_LONG:
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+ kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
break;
case OP_SHL_LONG:
case OP_SHR_LONG:
case OP_USHR_LONG:
/* shift distance is Int, making these different from other binops */
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+ kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
break;
case OP_ADD_FLOAT:
case OP_SUB_FLOAT:
case OP_DIV_FLOAT:
case OP_REM_FLOAT:
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+ kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
break;
case OP_ADD_DOUBLE:
case OP_SUB_DOUBLE:
case OP_DIV_DOUBLE:
case OP_REM_DOUBLE:
checkBinop(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+ kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+ &failure);
break;
case OP_ADD_INT_2ADDR:
case OP_SUB_INT_2ADDR:
case OP_SHR_INT_2ADDR:
case OP_USHR_INT_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+ kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
break;
case OP_AND_INT_2ADDR:
case OP_OR_INT_2ADDR:
case OP_XOR_INT_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+ kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
break;
case OP_DIV_INT_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+ kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
break;
case OP_ADD_LONG_2ADDR:
case OP_SUB_LONG_2ADDR:
case OP_OR_LONG_2ADDR:
case OP_XOR_LONG_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+ kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
break;
case OP_SHL_LONG_2ADDR:
case OP_SHR_LONG_2ADDR:
case OP_USHR_LONG_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+ kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
break;
case OP_ADD_FLOAT_2ADDR:
case OP_SUB_FLOAT_2ADDR:
case OP_DIV_FLOAT_2ADDR:
case OP_REM_FLOAT_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+ kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
break;
case OP_ADD_DOUBLE_2ADDR:
case OP_SUB_DOUBLE_2ADDR:
case OP_DIV_DOUBLE_2ADDR:
case OP_REM_DOUBLE_2ADDR:
checkBinop2addr(workRegs, insnRegCount, &decInsn,
- kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+ kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+ &failure);
break;
case OP_ADD_INT_LIT16:
case OP_RSUB_INT:
case OP_DIV_INT_LIT16:
case OP_REM_INT_LIT16:
checkLitop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, false, &okay);
+ kRegTypeInteger, kRegTypeInteger, false, &failure);
break;
case OP_AND_INT_LIT16:
case OP_OR_INT_LIT16:
case OP_XOR_INT_LIT16:
checkLitop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, true, &okay);
+ kRegTypeInteger, kRegTypeInteger, true, &failure);
break;
case OP_ADD_INT_LIT8:
case OP_RSUB_INT_LIT8:
case OP_SHR_INT_LIT8:
case OP_USHR_INT_LIT8:
checkLitop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, false, &okay);
+ kRegTypeInteger, kRegTypeInteger, false, &failure);
break;
case OP_AND_INT_LIT8:
case OP_OR_INT_LIT8:
case OP_XOR_INT_LIT8:
checkLitop(workRegs, insnRegCount, &decInsn,
- kRegTypeInteger, kRegTypeInteger, true, &okay);
+ kRegTypeInteger, kRegTypeInteger, true, &failure);
break;
case OP_INVOKE_VIRTUAL_QUICK_RANGE:
case OP_INVOKE_SUPER_QUICK:
case OP_INVOKE_SUPER_QUICK_RANGE:
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
/* these should never appear */
case OP_UNUSED_FD:
case OP_UNUSED_FE:
case OP_UNUSED_FF:
- okay = false;
+ failure = VERIFY_ERROR_GENERIC;
break;
/*
*/
}
- if (!okay) {
+ if (!VERIFY_OK(failure)) {
LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x\n",
decInsn.opCode, insnIdx);
goto bail;