diff options
| author | Andy McFadden <fadden@android.com> | 2010-09-28 14:43:28 -0700 |
|---|---|---|
| committer | Andy McFadden <fadden@android.com> | 2010-09-28 14:43:28 -0700 |
| commit | de9cdfa9d6d5fa5c46a0ec0f3f1e8de08a688841 (patch) | |
| tree | d647dc1768670e9cb8b97f391d23caad6c3b8e82 | |
| parent | b36ea7918612c81cb42ff2021443358a9f109a6d (diff) | |
| download | android_dalvik-de9cdfa9d6d5fa5c46a0ec0f3f1e8de08a688841.tar.gz android_dalvik-de9cdfa9d6d5fa5c46a0ec0f3f1e8de08a688841.tar.bz2 android_dalvik-de9cdfa9d6d5fa5c46a0ec0f3f1e8de08a688841.zip | |
Fix verification of switch offsets in large methods.
The verifier was only using the low 16 bits when checking the offset
to a switch table. This was failing on really large methods.
We also blew up the arbitrary size cap again, so I made it a warning
rather than a failure (it really wasn't doing anybody any good).
Changed to width-specific types for the various offsets and sizes.
Bug 3044850.
(cherry-pick+squash from dalvik-dev)
Change-Id: Ic7ebb86728cb39151f617a3e69e1c1994e61b5d9
| -rw-r--r-- | vm/analysis/CodeVerify.c | 5 | ||||
| -rw-r--r-- | vm/analysis/VerifySubs.c | 13 |
2 files changed, 9 insertions, 9 deletions
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c index 3c7be1162..ef6872e62 100644 --- a/vm/analysis/CodeVerify.c +++ b/vm/analysis/CodeVerify.c @@ -3094,11 +3094,10 @@ bool dvmVerifyCodeFlow(VerifierData* vdata) dvmFindSystemClassNoInit("Ljava/lang/Object;"); if (meth->registersSize * insnsSize > 4*1024*1024) { - /* should probably base this on actual memory requirements */ LOG_VFY_METH(meth, - "VFY: arbitrarily rejecting large method (regs=%d count=%d)\n", + "VFY: warning: method is huge (regs=%d insnsSize=%d)\n", meth->registersSize, insnsSize); - goto bail; + /* might be bogus data, might be some huge generated method */ } /* diff --git a/vm/analysis/VerifySubs.c b/vm/analysis/VerifySubs.c index 2285aef6c..8334a0caf 100644 --- a/vm/analysis/VerifySubs.c +++ b/vm/analysis/VerifySubs.c @@ -176,18 +176,19 @@ bool dvmSetTryFlags(const Method* meth, InsnFlags* insnFlags) bool dvmCheckSwitchTargets(const Method* meth, InsnFlags* insnFlags, int curOffset) { - const int insnCount = dvmGetMethodInsnsSize(meth); + const s4 insnCount = dvmGetMethodInsnsSize(meth); const u2* insns = meth->insns + curOffset; const u2* switchInsns; u2 expectedSignature; - int switchCount, tableSize; - int offsetToSwitch, offsetToKeys, offsetToTargets, targ; - int offset, absOffset; + u4 switchCount, tableSize; + s4 offsetToSwitch, offsetToKeys, offsetToTargets; + s4 offset, absOffset; + u4 targ; assert(curOffset >= 0 && curOffset < insnCount); /* make sure the start of the switch is in range */ - offsetToSwitch = (s2) insns[1]; + offsetToSwitch = insns[1] | ((s4) insns[2]) << 16; if (curOffset + offsetToSwitch < 0 || curOffset + offsetToSwitch + 2 >= insnCount) { @@ -231,7 +232,7 @@ bool dvmCheckSwitchTargets(const Method* meth, InsnFlags* insnFlags, } /* make sure the end of the switch is in range */ - if (curOffset + offsetToSwitch + tableSize > insnCount) { + if (curOffset + offsetToSwitch + tableSize > (u4) insnCount) { LOG_VFY_METH(meth, "VFY: invalid switch end: at %d, switch offset %d, end %d, count %d\n", curOffset, offsetToSwitch, curOffset + offsetToSwitch + tableSize, |
