summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Readme.html2
-rw-r--r--javassist.jarbin699131 -> 699781 bytes
-rw-r--r--src/main/javassist/bytecode/BadBytecode.java6
-rw-r--r--src/main/javassist/bytecode/stackmap/MapMaker.java55
-rw-r--r--src/test/javassist/bytecode/StackMapTest.java60
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
index dd1d5843..87393d38 100644
--- a/javassist.jar
+++ b/javassist.jar
Binary files differ
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");