diff options
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | javassist.jar | bin | 699131 -> 699781 bytes | |||
-rw-r--r-- | src/main/javassist/bytecode/BadBytecode.java | 6 | ||||
-rw-r--r-- | src/main/javassist/bytecode/stackmap/MapMaker.java | 55 | ||||
-rw-r--r-- | src/test/javassist/bytecode/StackMapTest.java | 60 |
5 files changed, 112 insertions, 11 deletions
diff --git a/Readme.html b/Readme.html index 72933367..4a5e00a6 100644 --- a/Readme.html +++ b/Readme.html @@ -284,7 +284,7 @@ see javassist.Dump. <p>-version 3.17 <ul> <li>OSGi bundle info is now included in the jar file. - <li>JIRA JASSIST-160, 163, 166, 168, 170, 171, 174 have been fixed. + <li>JIRA JASSIST-160, 163, 166, 168, 170, 171, 174, 175 have been fixed. </ul> <p>-version 3.16.1 on March 6, 2012 diff --git a/javassist.jar b/javassist.jar Binary files differindex dd1d5843..87393d38 100644 --- a/javassist.jar +++ b/javassist.jar diff --git a/src/main/javassist/bytecode/BadBytecode.java b/src/main/javassist/bytecode/BadBytecode.java index 71e5bb9d..9959ae6c 100644 --- a/src/main/javassist/bytecode/BadBytecode.java +++ b/src/main/javassist/bytecode/BadBytecode.java @@ -31,4 +31,10 @@ public class BadBytecode extends Exception { public BadBytecode(String msg, Throwable cause) { super(msg, cause); } + + public BadBytecode(MethodInfo minfo, Throwable cause) { + super(minfo.toString() + " in " + + minfo.getConstPool().getClassName() + + ": " + cause.getMessage(), cause); + } } diff --git a/src/main/javassist/bytecode/stackmap/MapMaker.java b/src/main/javassist/bytecode/stackmap/MapMaker.java index b846661b..3c96a36a 100644 --- a/src/main/javassist/bytecode/stackmap/MapMaker.java +++ b/src/main/javassist/bytecode/stackmap/MapMaker.java @@ -96,7 +96,13 @@ public class MapMaker extends Tracer { return null; MapMaker mm = new MapMaker(classes, minfo, ca); - mm.make(blocks, ca.getCode()); + try { + mm.make(blocks, ca.getCode()); + } + catch (BadBytecode bb) { + throw new BadBytecode(minfo, bb); + } + return mm.toStackMap(blocks); } @@ -117,7 +123,12 @@ public class MapMaker extends Tracer { return null; MapMaker mm = new MapMaker(classes, minfo, ca); - mm.make(blocks, ca.getCode()); + try { + mm.make(blocks, ca.getCode()); + } + catch (BadBytecode bb) { + throw new BadBytecode(minfo, bb); + } return mm.toStackMap2(minfo.getConstPool(), blocks); } @@ -137,7 +148,7 @@ public class MapMaker extends Tracer { { make(code, blocks[0]); try { - fixTypes(blocks); + fixTypes(code, blocks); } catch (NotFoundException e) { throw new BadBytecode("failed to resolve types", e); } @@ -276,22 +287,40 @@ public class MapMaker extends Tracer { * Since SCCs are found in the topologically sorted order, * their types are also fixed when they are found. */ - private void fixTypes(TypedBlock[] blocks) throws NotFoundException { + private void fixTypes(byte[] code, TypedBlock[] blocks) throws NotFoundException, BadBytecode { ArrayList preOrder = new ArrayList(); int len = blocks.length; int index = 0; for (int i = 0; i < len; i++) { TypedBlock block = blocks[i]; - int n = block.localsTypes.length; - for (int j = 0; j < n; j++) - index = block.localsTypes[j].dfs(preOrder, index, classPool); + if (block.localsTypes == null) // if block is dead code + fixDeadcode(code, block); + else { + int n = block.localsTypes.length; + for (int j = 0; j < n; j++) + index = block.localsTypes[j].dfs(preOrder, index, classPool); - n = block.stackTop; - for (int j = 0; j < n; j++) - index = block.stackTypes[j].dfs(preOrder, index, classPool); + n = block.stackTop; + for (int j = 0; j < n; j++) + index = block.stackTypes[j].dfs(preOrder, index, classPool); + } } } + private void fixDeadcode(byte[] code, TypedBlock block) throws BadBytecode { + int pos = block.position; + int len = block.length - 3; + if (len < 0) + throw new BadBytecode("dead code detected at " + pos + + ". No stackmap table generated."); + + for (int k = 0; k < len; k++) + code[pos + k] = Bytecode.NOP; + + code[pos + len] = (byte)Bytecode.GOTO; + ByteArray.write16bit(-len, code, pos + len + 1); + } + // Phase 3 public StackMapTable toStackMap(TypedBlock[] blocks) { @@ -314,6 +343,12 @@ public class MapMaker extends Tracer { offsetDelta = bb.length - 1; prev = bb; } + else if (bb.incoming == 0) { + // dead code. + writer.sameFrame(offsetDelta); + offsetDelta = bb.length - 1; + prev = bb; + } else offsetDelta += bb.length; } diff --git a/src/test/javassist/bytecode/StackMapTest.java b/src/test/javassist/bytecode/StackMapTest.java index 876b335e..0fdcf2cd 100644 --- a/src/test/javassist/bytecode/StackMapTest.java +++ b/src/test/javassist/bytecode/StackMapTest.java @@ -647,6 +647,66 @@ public class StackMapTest extends TestCase { } } + public void testJIRA175() throws Exception { + CtClass cc = loader.get("javassist.bytecode.StackMapTest$C5"); + cc.getDeclaredMethod("setter").instrument(new javassist.expr.ExprEditor() { + @Override + public void edit(javassist.expr.FieldAccess f) throws javassist.CannotCompileException { + if (!f.where().getMethodInfo().isMethod()) + return; + + f.replace("{ $_ = $proceed($$); if (false) return $_;}"); + } + }); + cc.writeFile(); + Object t1 = make(cc.getName()); + assertEquals(3, invoke(t1, "test")); + } + + public static class C5 { + String value; + int ivalue; + public int test() { + setter("foo"); + return value.length(); + } + + public void setter(String s) { + value = s; + ivalue = s.length(); + } + } + + public void testJIRA175b() throws Exception { + CtClass cc = loader.get("javassist.bytecode.StackMapTest$C6"); + try { + cc.getDeclaredMethod("setter").instrument(new javassist.expr.ExprEditor() { + public void edit(javassist.expr.FieldAccess f) throws javassist.CannotCompileException { + if (!f.where().getMethodInfo().isMethod()) + return; + + f.replace("{ $_ = $proceed($$); return $_;}"); + } + }); + fail("deadcode detection"); + } + catch (javassist.CannotCompileException e) {} + } + + public static class C6 { + String value; + int ivalue; + public int test() { + setter("foo"); + return value.length(); + } + + public void setter(String s) { + value = s; + ivalue = s.length(); + } + } + public void tstCtClassType() throws Exception { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("javassist.CtClassType"); |