diff options
-rw-r--r-- | Readme.html | 2 | ||||
-rw-r--r-- | src/main/javassist/bytecode/StackMapTable.java | 10 | ||||
-rw-r--r-- | src/test/javassist/bytecode/StackMapTest.java | 77 |
3 files changed, 85 insertions, 4 deletions
diff --git a/Readme.html b/Readme.html index 5cfff1f0..cd9ee855 100644 --- a/Readme.html +++ b/Readme.html @@ -293,7 +293,7 @@ see javassist.Dump. <p>-version 3.28 <ul> - <li>GitHub Issue #328, #339, #357. + <li>GitHub Issue #328, #339, #350, #357. </ul> <p>-version 3.27 on March 19, 2020 diff --git a/src/main/javassist/bytecode/StackMapTable.java b/src/main/javassist/bytecode/StackMapTable.java index 81622200..62a6aca0 100644 --- a/src/main/javassist/bytecode/StackMapTable.java +++ b/src/main/javassist/bytecode/StackMapTable.java @@ -204,8 +204,11 @@ public class StackMapTable extends AttributeInfo { } else if (type < 128) pos = sameLocals(pos, type); - else if (type < 247) - throw new BadBytecode("bad frame_type in StackMapTable"); + else if (type < 247) { + throw new BadBytecode( + "bad frame_type " + type + " in StackMapTable (pos: " + + pos + ", frame no.:" + nth + ")"); + } else if (type == 247) // SAME_LOCALS_1_STACK_ITEM_EXTENDED pos = sameLocals(pos, type); else if (type < 251) { @@ -890,11 +893,12 @@ public class StackMapTable extends AttributeInfo { match = oldPos <= where && where < position; if (match) { + int current = info[pos] & 0xff; int newDelta = offsetDelta + gap; position += gap; if (newDelta < 64) info[pos] = (byte)(newDelta + base); - else if (offsetDelta < 64) { + else if (offsetDelta < 64 && current != entry) { byte[] newinfo = insertGap(info, pos, 2); newinfo[pos] = (byte)entry; ByteArray.write16bit(newDelta, newinfo, pos + 1); diff --git a/src/test/javassist/bytecode/StackMapTest.java b/src/test/javassist/bytecode/StackMapTest.java index 7ea415a9..a0a4f1b1 100644 --- a/src/test/javassist/bytecode/StackMapTest.java +++ b/src/test/javassist/bytecode/StackMapTest.java @@ -923,4 +923,81 @@ public class StackMapTest extends TestCase { else ci.insert(newCode.get()); } + + public void testIssue350() throws Exception { + byte sameLocals1StackItemFrameExtended = 247 - 256; + byte sameFrameExtended = 251 - 256; + byte appendFrame = 252 - 256; + ConstPool cp = new ConstPool("Test"); + StackMapTable stmt; + int originalLength; + + stmt = new StackMapTable(cp, new byte[] { + 0, 1, + sameLocals1StackItemFrameExtended, 0, 63, 1 + }); + originalLength = stmt.info.length; + assertEquals(63, stmt.info[4]); + stmt.shiftPc(0, 2, false); + assertEquals(originalLength, stmt.info.length); + assertEquals(65, stmt.info[4]); + + stmt = new StackMapTable(cp, new byte[] { + 0, 1, + sameFrameExtended, 0, 63 + }); + originalLength = stmt.info.length; + assertEquals(63, stmt.info[4]); + stmt.shiftPc(0, 2, false); + assertEquals(originalLength, stmt.info.length); + assertEquals(65, stmt.info[4]); + + stmt = new StackMapTable(cp, new byte[] { + 0, 2, + sameLocals1StackItemFrameExtended, 0, 63, 1, + sameFrameExtended, 0, 63 + }); + originalLength = stmt.info.length; + assertEquals(63, stmt.info[4]); + assertEquals(63, stmt.info[8]); + stmt.shiftPc(0, 2, false); + assertEquals(originalLength, stmt.info.length); + assertEquals(65, stmt.info[4]); + assertEquals(63, stmt.info[8]); + stmt.shiftPc(100, 2, false); + assertEquals(65, stmt.info[4]); + assertEquals(65, stmt.info[8]); + + // Actual StackMapTable reported in https://github.com/jboss-javassist/javassist/issues/350. + stmt = new StackMapTable(cp, new byte[] { + 0, 7, // size + sameLocals1StackItemFrameExtended, 0, 76, 7, 2, 206 - 256, + sameLocals1StackItemFrameExtended, 0, 63, 7, 2, 221 - 256, + appendFrame, 0, 63, 7, 0, 14, + appendFrame, 0, 43, 7, 2, 225 - 256, 1, + 74, 7, 0, 19, // same_locals_1_stack_item_frame (not extended) + appendFrame, 0, 23, 7, 0, 19, + 66, 7, 2, 225 - 256 // same_locals_1_stack_item_frame (not extended) + }); + assertEquals(63, stmt.info[10]); + originalLength = stmt.info.length; + + stmt.shiftPc(100, 2, false); + assertEquals(originalLength, stmt.info.length); + assertEquals(65, stmt.info[10]); + } + + public static void dump(byte[] content) { + final int bytesPerLine = 16; + for (int i = 0; i < content.length; i += bytesPerLine) { + for (int j = 0; j < bytesPerLine && i + j < content.length; j++) { + int unsignedByte = content[i + j]; + if (unsignedByte < 0) { + unsignedByte = 256 + unsignedByte; + } + System.out.print(unsignedByte + ", "); + } + System.out.println(); + } + } } |