[JBoss JIRA] Created: (JASSIST-71) Array access replacement generates invalid bytecode when padding is required
by Jason T. Greene (JIRA)
Array access replacement generates invalid bytecode when padding is required
----------------------------------------------------------------------------
Key: JASSIST-71
URL: https://jira.jboss.org/jira/browse/JASSIST-71
Project: Javassist
Issue Type: Bug
Reporter: Jason T. Greene
Assignee: Shigeru Chiba
When an array access instruction is replaced before a switch instruction, and padding is added to align the switch, the array instruction remains, which is invalid:
public void test();
Code:
Stack=2, Locals=2, Args_size=1
0: aconst_null
1: astore_1
2: invokestatic #17; //Method $SWITCH_TABLE$RULE_TYPE:()[I
5: aload_1
6: invokevirtual #20; //Method RULE_TYPE.ordinal:()I
9: invokestatic #67; //Method arrayReadInt:(Ljava/lang/Object;I)I
12: nop
13: iaload <=========================== INVALID!!!!!!!!!!!!
14: tableswitch{ //1 to 1
1: 32;
default: 32 }
32: return
This is typically caught by the bytecode verifier
java.lang.VerifyError: (class: com/lm/dataModel/rules/StatusRule, method: propagateFromHereOnUpTree signature: (Lcom/lm/dataModel/ANode;Lcom/lm/dataModel/ANode$Source;Lcom/lm/dataModel/ANode$StatusValue;)Z) Unable to pop operand off an empty stack
at com.lm.dataModel.ANode.setStatusValueWithPropagation(ANode.java:301)
at com.lm.seem.StatusTableModel.setValueAt(StatusTableModel.java:133)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 9 months
[JBoss JIRA] Created: (JASSIST-72) Instrumenting write access using CodeConverter.replaceArrayAccess(...) causes VerifyError (Unable to pop operand off an empty stack) - buggy aastore
by Martin Burger (JIRA)
Instrumenting write access using CodeConverter.replaceArrayAccess(...) causes VerifyError (Unable to pop operand off an empty stack) - buggy aastore
----------------------------------------------------------------------------------------------------------------------------------------------------
Key: JASSIST-72
URL: https://jira.jboss.org/jira/browse/JASSIST-72
Project: Javassist
Issue Type: Bug
Environment: javassist 3.9.0.GA
Reporter: Martin Burger
Assignee: Shigeru Chiba
I use Javassist to instrument class files in order to catch some runtime information. Basically, I insert probes to get information about method calls, field accesses, and so on. This includes access to arrays. Unfortunately, when I instrument array accesses using CodeConverter.replaceArrayAccess(...) the Java verifier throws an exception while loading the changed method: Unable to pop operand off an empty stack.
Instrumenting array accesses is one instrumentation of many. If I disable instrumentation of array accesses, the instrumented program will run and I will get runtime information about method calls etc. As soon as I enable the instrumentation of arrays, the byte code created by javassist causes the java.lang.VerifyError mentioned above.
The buggy byte code instruction seems to be:
7016: anewarray #51; //class java/lang/Object
7019: dup
7020: iconst_0
7021: iload_1
7022: bipush 56
7024: if_icmpne 7036
7027: ldc_w #5369; //String 8
7030: nop
7031: nop
7032: nop
7033: goto 7042
7036: ldc_w #5371; //String 9
7039: nop
7040: nop
7041: nop
7042: invokestatic #5373;
7045: nop
7046: aastore <-- causes VerifyError
At least when executing aastore the stack is empty already.
The original source code:
if (base == 8 && c >= '8') {
Object[] errArgs = { c == '8' ? "8" : "9" };
reportCurrentLineWarning(
"msg.bad.octal.literal", errArgs);
base = 10;
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 9 months
[JBoss JIRA] Created: (JASSIST-80) Editing MethodCall produces incorrect byte code | java.lang.VerifyError: Illegal target of jump or branch | invalid instruction
by Martin Burger (JIRA)
Editing MethodCall produces incorrect byte code | java.lang.VerifyError: Illegal target of jump or branch | invalid instruction
-------------------------------------------------------------------------------------------------------------------------------
Key: JASSIST-80
URL: https://jira.jboss.org/jira/browse/JASSIST-80
Project: Javassist
Issue Type: Bug
Affects Versions: 3.10.0.GA
Environment: $ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)
Reporter: Martin Burger
Assignee: Shigeru Chiba
Note: Most likely this issue is related to JASSIST-79.
I instrument method calls in a class called org.mozilla.javascript.TokenStream.
If I run (or, load) this class, a java.lang.VerifyError will be thrown:
Exception in thread "main" java.lang.VerifyError: (class: org/mozilla/javascript/TokenStream, method: getToken$JINSI_4etOXffNDXVw signature: ()I) Illegal target of jump or branch
It seems Javassist introduces a defective goto statement at position 33217 in method getToken$JINSI_4etOXffNDXVw:
33217 goto 465
The corresponding Java code (excerpt):
case '-':
if (matchChar('=')) {
this.op = SUB;
c = ASSIGN;
} else if (matchChar('-')) {
if (0 == (flags & TSF_DIRTYLINE)) {
// treat HTML end-comment after possible whitespace
// after line start as comment-utill-eol
if (matchChar('>')) {
skipLine();
continue retry;
}
}
c = DEC;
} else {
c = SUB;
}
flags |= TSF_DIRTYLINE;
return c;
I think the continue statement is related to this defect.
JAD fails to decompile the instrumented class:
ERROR: invalid instruction at 33217 in the method getToken$JINSI_4etOXffNDXVw. The method will be decompiled incorrectly.
Javassist's framedump fails, too:
Exception in thread "main" java.lang.RuntimeException: javassist.bytecode.BadBytecode: Stack is empty[pos = 465]
at javassist.bytecode.analysis.FramePrinter.print(FramePrinter.java:89)
at javassist.bytecode.analysis.FramePrinter.print(FramePrinter.java:60)
at javassist.bytecode.analysis.FramePrinter.print(FramePrinter.java:51)
at javassist.tools.framedump.main(framedump.java:45)
Caused by: javassist.bytecode.BadBytecode: Stack is empty[pos = 465]
at javassist.bytecode.analysis.Analyzer.analyzeNextEntry(Analyzer.java:179)
at javassist.bytecode.analysis.Analyzer.analyze(Analyzer.java:143)
at javassist.bytecode.analysis.FramePrinter.print(FramePrinter.java:87)
... 3 more
Caused by: java.lang.IndexOutOfBoundsException: Stack is empty
at javassist.bytecode.analysis.Frame.pop(Frame.java:130)
at javassist.bytecode.analysis.Executor.simplePop(Executor.java:970)
at javassist.bytecode.analysis.Executor.evalStore(Executor.java:869)
at javassist.bytecode.analysis.Executor.execute(Executor.java:188)
at javassist.bytecode.analysis.Analyzer.analyzeNextEntry(Analyzer.java:177)
... 5 more
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 9 months
[JBoss JIRA] Created: (JASSIST-86) Make concurrent calls to getRefClasses() safe.
by Shigeru Chiba (JIRA)
Make concurrent calls to getRefClasses() safe.
----------------------------------------------
Key: JASSIST-86
URL: https://jira.jboss.org/jira/browse/JASSIST-86
Project: Javassist
Issue Type: Bug
Affects Versions: 3.10.0.GA
Reporter: Shigeru Chiba
Assignee: Shigeru Chiba
There is a race condition when getRefClasses is called twice concurrently on
the same class - one of the chains in HashMap for collision resolution can become
cyclic, i.e. an infinitely long list, causing iteration on the list to enter an
infinite loop.
On a CtClass ct, the call path leading to the problem is:
ct.getRefClasses() -> ct.renameClass() (it's a fake renameClass(), which does
not rename anything) -> ct.constPool.renameClass()
One can thus have concurrent calls to ct.constPool.renameClass(); a constPool
then recreates the internal HashMap, i.e. reinserts again all elements into
cp.classes (not a temporary map), so we have concurrent accesses to this map.
In particular, since there can be a collision (as happened for me), the
collision chain could become cyclic.
This was found through remote debugging on a concurrent program using Javassist
(attaching after a series of run-client invocations ended in a crash). It was a
real-world program, not a client written on purpose to show this.
This patch solves the problem well, and was tested in a configuration which caused a
lot of crashes and stopped causing any.
Lots of better fixes to this could be thought, but they're more invasive.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 9 months
[JBoss JIRA] Created: (JASSIST-93) VerifyError with addLocalVariable() and insertAfter()
by Joerg Plewe (JIRA)
VerifyError with addLocalVariable() and insertAfter()
-----------------------------------------------------
Key: JASSIST-93
URL: https://jira.jboss.org/jira/browse/JASSIST-93
Project: Javassist
Issue Type: Bug
Environment: javassist 3.11 and 3.5
JDK6
Reporter: Joerg Plewe
Assignee: Shigeru Chiba
Hi all!
This is my first post here and I am a javassist newbie. So hopefully my problem can easily be solved.
>From a real usecase, I condensed the following fragment demonstrating my problem:
Code:
ClassPool cp = ClassPool.getDefault();
CtClass cl = cp.getCtClass("jatest.Test");
CtMethod m = cl.getDeclaredMethod("foo");
m.addLocalVariable("bar", CtClass.longType);
m.insertAfter("bar;", true);
Object o = cl.toClass().newInstance();
The class 'Test' is as simple as it can get:
Code:
public class Test {
public void foo() {}
}
Running the code delivers a VerifyError which I think it shouldn't:
Code:
Exception in thread "main" java.lang.VerifyError: (class: jatest/Test, method: foo signature: ()V) Register pair 1/2 contains
wrong type
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
at java.lang.Class.getConstructor0(Class.java:2699)
at java.lang.Class.newInstance0(Class.java:326)
at java.lang.Class.newInstance(Class.java:308)
at jatest.Main.main(Main.java:27)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
14 years, 9 months