Menu

#598 Retrace file name parsing in case of negative line numbers

v5.2
closed-fixed
None
5
2016-10-23
2016-04-07
Neeme Praks
No

I use Proguard 5.2.1.

Original issue: I have a stacktrace with more than a 100 frames and retrace never finishes processing it (I gave up waiting after 10 minutes).

Upon further investigation I isolated the problem to stack frames such as this:
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)

I ran some tests by feeding retrace a stack trace with single stack frame and measuring, how long it took to process. Results:

sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:2), time: 0.127 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl:-2), time: 1.4 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.:-2), time: 2.5 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.j:-2), time: 4.6 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.ja:-2), time: 8.5 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.jav:-2), time: 15.6 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2), time: 34 seconds
sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.javaa:-2), time: 67 seconds

Note how, in case of negative line number, the amount it takes to process the stack frame increases exponentially with each additional character added to the file name.

My original stack trace had one particularly nasty stack frame with negative line number:
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeConstructorAccessorImpl.java:-2)
"NativeConstructorAccessorImpl.java" file name is 34 characters long and would have taken ~20 minutes to process (extrapolating from the exponential growth above).

Obfuscation map size does not seem to matter.

I took a thread dump and main thread is busy using regular expressions to parse the stack frames:

"main" #1 prio=5 os_prio=31 tid=0x00007f8a4a00b800 nid=0x1703 runnable [0x0000700000217000]
   java.lang.Thread.State: RUNNABLE
    at java.util.regex.Pattern$Branch.match(Pattern.java:4600)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4794)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4279)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.matchInit(Pattern.java:4804)
    at java.util.regex.Pattern$Prolog.match(Pattern.java:4741)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3798)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4279)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Ques.match(Pattern.java:4182)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$Ques.match(Pattern.java:4182)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3798)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4794)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3798)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.match(Pattern.java:4785)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4717)
    at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3798)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4272)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Loop.matchInit(Pattern.java:4804)
    at java.util.regex.Pattern$Prolog.match(Pattern.java:4741)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4279)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4234)
    at java.util.regex.Pattern$Slice.match(Pattern.java:3972)
    at java.util.regex.Pattern$Bound.match(Pattern.java:5329)
    at java.util.regex.Pattern$Curly.match1(Pattern.java:4287)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4236)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4658)
    at java.util.regex.Pattern$Branch.match(Pattern.java:4604)
    at java.util.regex.Matcher.match(Matcher.java:1270)
    at java.util.regex.Matcher.matches(Matcher.java:604)
    at proguard.retrace.FramePattern.parse(FramePattern.java:138)
    at proguard.retrace.ReTrace.retrace(ReTrace.java:97)
    at proguard.retrace.ReTrace.main(ReTrace.java:276)
1 Attachments

Discussion

  • Eric Lafortune

    Eric Lafortune - 2016-04-17

    Thanks for the report; that's an interesting effect. I've fixed the regular expressions, now also allowing negative line numbers, in proguard/retrace/FramePattern.java:

    private static final String REGEX_SOURCE_FILE = "[^:()]+";
    private static final String REGEX_LINE_NUMBER = "-?\\b\\d+\\b";
    
     
  • Eric Lafortune

    Eric Lafortune - 2016-04-17
    • status: open --> open-fixed
    • assigned_to: Eric Lafortune
     
  • Eric Lafortune

    Eric Lafortune - 2016-10-23
    • Status: open-fixed --> closed-fixed
     

Log in to post a comment.