Re: Re: NOP ATHROW hack defeated !

Rémi Forax <[email protected]>
Newsgroups gmane.comp.java.objectweb.asm
Message-ID <[email protected]>
On 05/06/2011 09:26 AM, Charles Oliver Nutter wrote:
> I may have been mistakend about the exact errors below...will update shortly.
>
> - Charlie

If you want the exact line number,
you can use all/asm-debug-all-4.0.jar

Rémi

> On Fri, May 6, 2011 at 2:17 AM, Charles Oliver Nutter
> <[email protected]>  wrote:
>> Sorry for the delay. This appears to cause failures due to invalid
>> classfiles in JRuby, at about the place where it blew up because of
>> the dead code before:
>>
>> ~/projects/jruby ➔ jruby -Xjruby.invokedynamic=false test/testCompiler.rb
>> ..........................................................................................................................................FF........................................
>> --------------------------------------------------------------------------------
>> FAILED  139 unexpected exception java.lang.ClassFormatError: Invalid
>> code attribute name index 65 in class file testCompiler135--
>> test/testCompiler.rb:474:in `(root)'
>> FAILED  140 unexpected exception java.lang.ClassFormatError: Truncated
>> class file-- test/testCompiler.rb:489:in `(root)'
>> --------------------------------------------------------------------------------
>> Tests: 180. (Ok: 178; Failed: 2)
>>
>> Attempting to output the bytecode it produces yields an
>> ArrayIndexOutOfBoundsException in most cases I attempted to
>> investigate. Here's the actual exceptions it's raising (sorry, I don't
>> know how to build an ASM that has line numbers):
>>
>> ~/projects/jruby ➔ jruby -X+C -d -e "def foo; begin; return 4; rescue;
>> end; return 3; end; foo"
>> warning: could not compile: -e; full trace follows
>> java.lang.ClassFormatError: Invalid code attribute name index 65 in
>> class file ruby/__dash_e__
>>         at java.lang.ClassLoader.defineClass1(Native Method)
>>         at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
>>         at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
>>         at org.jruby.util.JRubyClassLoader.defineClass(JRubyClassLoader.java:76)
>>         at org.jruby.compiler.impl.StandardASMCompiler.loadClass(StandardASMCompiler.java:219)
>>         at org.jruby.Ruby.tryCompile(Ruby.java:655)
>>         at org.jruby.Ruby.tryCompile(Ruby.java:627)
>>         at org.jruby.Ruby.runNormally(Ruby.java:567)
>>         at org.jruby.Ruby.runFromMain(Ruby.java:424)
>>         at org.jruby.Main.doRunFromMain(Main.java:278)
>>         at org.jruby.Main.internalRun(Main.java:198)
>>         at org.jruby.Main.run(Main.java:164)
>>         at org.jruby.Main.run(Main.java:148)
>>         at org.jruby.Main.main(Main.java:128)
>> RuntimeError: could not compile and compile mode is 'force': -e
>>
>> ~/projects/jruby ➔ jruby -X+C -d -e "begin; x = while true; break 5;
>> end; ensure; end"
>> warning: could not compile: -e; full trace follows
>> java.lang.ClassFormatError: Invalid code attribute name index 55 in
>> class file ruby/__dash_e__
>>         at java.lang.ClassLoader.defineClass1(Native Method)
>>         at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
>>         at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
>>         at org.jruby.util.JRubyClassLoader.defineClass(JRubyClassLoader.java:76)
>>         at org.jruby.compiler.impl.StandardASMCompiler.loadClass(StandardASMCompiler.java:219)
>>         at org.jruby.Ruby.tryCompile(Ruby.java:655)
>>         at org.jruby.Ruby.tryCompile(Ruby.java:627)
>>         at org.jruby.Ruby.runNormally(Ruby.java:567)
>>         at org.jruby.Ruby.runFromMain(Ruby.java:424)
>>         at org.jruby.Main.doRunFromMain(Main.java:278)
>>         at org.jruby.Main.internalRun(Main.java:198)
>>         at org.jruby.Main.run(Main.java:164)
>>         at org.jruby.Main.run(Main.java:148)
>>         at org.jruby.Main.main(Main.java:128)
>> RuntimeError: could not compile and compile mode is 'force': -e
>>
>> If you want to reproduce this, replace the ASM jars in JRuby's
>> build_lib, rebuild, and run the above command lines or
>> test/testCompiler.rb.
>>
>> - Charlie
>>
>> On Sun, May 1, 2011 at 10:15 AM, Eric Bruneton<[email protected]>  wrote:
>>> 01/05/2011 16:16, Rémi Forax wrote:
>>>> On 05/01/2011 11:09 AM, Eric Bruneton wrote:
>>>>> 30/04/2011 10:20, Eric Bruneton wrote:
>>>>>> 29/04/2011 03:04, Rémi Forax wrote:
>>>>>>> Charles Nutter (a JRuby guy) was able to generate a code that defeat
>>>>>>> the infamous NOP ... ATHROW hack.
>>>>>>>
>>>>>>> see http://asm.ow2.org/doc/developer-guide.html#deadcode
>>>>>>> for the background.
>>>>>>>
>>>>>>> Basically, when a code is dead, not reachable, ASM replaces the
>>>>>>> offending code by
>>>>>>> NOP ... ATHROW and generate a dedicated stackmap: []
>>>>>>> [java/lang/Throwable].
>>>>>>> But if the unreachable code is in a try/catch, we create a path
>>>>>>> where no
>>>>>>> local variable
>>>>>>> are available anymore. So the split verifier will reject the
>>>>>>> bytecode if
>>>>>>> a local variable is used in the exception handler of the try/catch.
>>>>>>>
>>>>>>> The program below generates a bytecode which is rejected by the split
>>>>>>> verifier.
>>>>>>> [forax@localhost asm4-test]$ java deadcode
>>>>>>> Exception in thread "main" java.lang.VerifyError: Stack map does not
>>>>>>> match the one at exception handler 7 in method
>>>>>>> deadcode.foo(Ljava/lang/Object;)V at offset 3
>>>>>>> at java.lang.Class.getDeclaredMethods0(Native Method)
>>>>>>> at java.lang.Class.privateGetDeclaredMethods(Class.java:2440)
>>>>>>> at java.lang.Class.getMethod0(Class.java:2683)
>>>>>>> at java.lang.Class.getMethod(Class.java:1618)
>>>>>>> at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:484)
>>>>>>> at
>>>>>>> sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:476)
>>>>>>>
>>>>>>>
>>>>>>> Eric, do you see a solution for that ?
>>>>>> I think we can find which locals to put in the stackmap frame generated
>>>>>> for a dead block by using the locals from the first frame of the
>>>>>> innermost exception handler for this block(*) (if any). Using the
>>>>>> innermost handler is necessary to get the most specific types for these
>>>>>> locals (the other handlers will necessarily have these types or super
>>>>>> types of these types in their stackmap frames, since they handle more
>>>>>> code). Also, since dead blocks are handled after the fix point algorithm
>>>>>> is finished, we have the final frames for the exception handlers at this
>>>>>> point.
>>>>>>
>>>>>> The only problem is that exception handlers do not have to be properly
>>>>>> nested (nothing enforces this in the specification, although compilers
>>>>>> always generate nested handlers because Java try/catch are nested by
>>>>>> construction). And in this case the "innermost handler" is not well
>>>>>> defined.
>>>>> there is another solution, which is simpler and works in all cases (I
>>>>> think): remove the exception handlers for deadcode (see attached patch).
>>>>>
>>>>> Eric
>>>> It seems the patch was too shy to show up :)
>>> oups! here it is
>>>
>>> Eric
>>>
message-footer.txt (text/plain, 238 B)
-- 
You receive this message as a subscriber of the [email protected] mailing list.
To unsubscribe: mailto:[email protected]
For general help: mailto:[email protected]?subject=help
OW2 mailing lists service home page: http://www.ow2.org/wws
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.