summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2010-09-28 14:43:28 -0700
committerAndy McFadden <fadden@android.com>2010-09-28 14:43:28 -0700
commitde9cdfa9d6d5fa5c46a0ec0f3f1e8de08a688841 (patch)
treed647dc1768670e9cb8b97f391d23caad6c3b8e82
parentb36ea7918612c81cb42ff2021443358a9f109a6d (diff)
downloadandroid_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.c5
-rw-r--r--vm/analysis/VerifySubs.c13
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,