Menu

#701 ProGuard 6.0.2: java.lang.VerifyError: Inconsistent stackmap frames

v6.0
closed-fixed
None
Medium
2018-05-07
2018-04-26
Freddy
No

ProGuard: 6.0.2 (however, fails also with previous versions)
Java: jdk1.8.0_162 (x64)
Platform: Windows 10

The following class cannot be loaded after obfuscation:

package test;
import java.io.IOException;
public class Problematic
{
public static interface Runner
{
public void run() throws IOException;
}

public static void retry(int a, long b, Runner r) throws IOException
{
    while (true)
    {
        try
        {
            r.run();
            return;
        } catch (IOException ex)
        {
            if (a <= 0)
                throw ex;
        }

        if (b > 0)
        {
            try
            {
                Thread.sleep(b);
            } catch (InterruptedException e)
            {
            }
        }
        a--;
    }
}

}

=========================== Invoked by:

package test;
import java.io.IOException;

public class Main {
public static void main(String[] args) {

    try
    {
        Problematic.retry(1, 2000, new Problematic.Runner()
        {
            @Override
            public void run() throws IOException
            {
                throw new IOException();
            }
        });
    } catch (IOException ex)
    {
        System.out.println(ex);
    }
}

public static void main2(String[] args) {
    try
    {
        Problematic.retry(1, 2000, new Problematic.Runner()
        {
            @Override
            public void run() throws IOException
            {
                throw new IOException();
            }
        });
    } catch (IOException ex)
    {
        System.out.println(ex);
    }
}

}

============================ ProGuard/ANT:

    <proguard>
                -injars '${dir.deploy}/jar/demo.jar'

                -libraryjars '${rt.jar}'

                -outjars '${dir.deploy}/jar/demo-pro.jar'

        -keep public class test.Main { 
            public static void main(java.lang.String[]); 
            public static void main2(java.lang.String[]); 
        }

    </proguard>

===== Error when executing code:

java.lang.VerifyError: Inconsistent stackmap frames at branch target 14
[java] Exception Details:
[java] Location:
[java] test/c.a(IJLtest/d;)V @14: ldc2_w
[java] Reason:
[java] Type 'java/io/IOException' (current frame, locals[1]) is not assignable to long (stack map, locals[1])
[java] Current Frame:
[java] bci: @9
[java] flags: { }
[java] locals: { integer, 'java/io/IOException', top, 'test/d' }
[java] stack: { integer }
[java] Stackmap Frame:
[java] bci: @14
[java] flags: { }
[java] locals: { integer, long, long_2nd, 'test/d' }
[java] stack: { }
[java] Bytecode:
[java] 0x0000000: 2db9 000a 0100 b14c 1a9d 0005 2bbf 1400
[java] 0x0000010: 0709 949e 000d 1400 07b8 0009 a700 0457
[java] 0x0000020: 8400 ffa7 ffdd
[java] Exception Handler Table:
[java] bci [0, 6] => handler: 7
[java] bci [22, 28] => handler: 31
[java] Stackmap Table:
[java] same_frame(@0)
[java] same_locals_1_stack_item_frame(@7,Object[#1])
[java] same_frame(@14)
[java] same_locals_1_stack_item_frame(@31,Object[#2])
[java] same_frame(@32)

===== Complete minimal test case (incl. jar files) in attachment

Thank you!

1 Attachments

Related

Bugs: #1
Bugs: #2

Discussion

  • Eric Lafortune

    Eric Lafortune - 2018-05-01

    Thanks for your detailed report. I can reproduce the issue and I'll see how we can solve it. For the time being, you can work around it with

    -optimizations !code/allocation/variable
    
     
  • Eric Lafortune

    Eric Lafortune - 2018-05-01
    • status: open --> open-accepted
    • assigned_to: Eric Lafortune
    • Priority: High --> Medium
     
  • Freddy

    Freddy - 2018-05-03

    Hi Eric, I can confirm that this workaround works. Thank you for this very useful software.

    Note to other people who may be worried about VerifyErrors at runtime: we currenly rely on a custom Ant Task that loads+resolves each obfuscated class. This way, it is possible to determine at build time whether the StackMap frames will be accepted by the JDK verifier. I cannot share that code, but it should be pretty easy to implement.

     
  • Eric Lafortune

    Eric Lafortune - 2018-05-03

    The bug has now been solved for the upcoming ProGuard update 6.0.3.

     
  • Eric Lafortune

    Eric Lafortune - 2018-05-03
    • status: open-accepted --> open-fixed
     
  • Eric Lafortune

    Eric Lafortune - 2018-05-07
    • Status: open-fixed --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB