Eric Bruneton (d7e25872) at 28 Mar 07:05
Fix ASM 9.7 release date.
Eric Bruneton (71dc100a) at 23 Mar 14:57
Update version number.
Eric Bruneton (c63c0d2a) at 23 Mar 14:51
Update version, history and news.
Eric Bruneton (0e57baee) at 23 Mar 14:29
Merge branch '318009-fix-analyzer-regression' into 'master'
Eric Bruneton (7a5bdbf2) at 21 Dec 12:17
All the given classes should yield no error when analysing them using BasicVerifier
and Analyzer
.
Analysing some classes using BasicVerifier
yields an AnalyzerException
.
An MRE is found below.
javap
is able to analyze the classes just fine (output is also found below).
I was able to track the source of this exception down to !373.
Changing the <=
back to <
fixes this error; also ASM 9.5
(compared to 9.6
or 9.7-SNAPSHOT
) did not yield this error.
The error was noticed in the test suite of https://github.com/ThexXTURBOXx/dex2jar
Classfile /C:/Coding/dex2jar/dex-translator/JSONDateConvertor.class
Last modified 01.12.2023; size 2302 bytes
SHA-256 checksum 7fe9ded8a180f4d81653168e874729b0597b570a7cb3d7a03dbd32448f8ff744
public class org.mortbay.util.ajax.JSONDateConvertor implements org.mortbay.util.ajax.JSON$Convertor
minor version: 0
major version: 50
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #2 // org/mortbay/util/ajax/JSONDateConvertor
super_class: #4 // java/lang/Object
interfaces: 1, fields: 3, methods: 6, attributes: 0
Constant pool:
#1 = Utf8 org/mortbay/util/ajax/JSONDateConvertor
#2 = Class #1 // org/mortbay/util/ajax/JSONDateConvertor
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 org/mortbay/util/ajax/JSON$Convertor
#6 = Class #5 // org/mortbay/util/ajax/JSON$Convertor
#7 = Utf8 _dateCache
#8 = Utf8 Lorg/mortbay/util/DateCache;
#9 = Utf8 _format
#10 = Utf8 Ljava/text/SimpleDateFormat;
#11 = Utf8 _fromJSON
#12 = Utf8 Z
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 (Z)V
#16 = NameAndType #13:#15 // "<init>":(Z)V
#17 = Methodref #2.#16 // org/mortbay/util/ajax/JSONDateConvertor."<init>":(Z)V
#18 = Utf8 (Ljava/lang/String;Ljava/util/TimeZone;Z)V
#19 = NameAndType #13:#14 // "<init>":()V
#20 = Methodref #4.#19 // java/lang/Object."<init>":()V
#21 = Utf8 org/mortbay/util/DateCache
#22 = Class #21 // org/mortbay/util/DateCache
#23 = Utf8 (Ljava/lang/String;)V
#24 = NameAndType #13:#23 // "<init>":(Ljava/lang/String;)V
#25 = Methodref #22.#24 // org/mortbay/util/DateCache."<init>":(Ljava/lang/String;)V
#26 = NameAndType #7:#8 // _dateCache:Lorg/mortbay/util/DateCache;
#27 = Fieldref #2.#26 // org/mortbay/util/ajax/JSONDateConvertor._dateCache:Lorg/mortbay/util/DateCache;
#28 = Utf8 setTimeZone
#29 = Utf8 (Ljava/util/TimeZone;)V
#30 = NameAndType #28:#29 // setTimeZone:(Ljava/util/TimeZone;)V
#31 = Methodref #22.#30 // org/mortbay/util/DateCache.setTimeZone:(Ljava/util/TimeZone;)V
#32 = NameAndType #11:#12 // _fromJSON:Z
#33 = Fieldref #2.#32 // org/mortbay/util/ajax/JSONDateConvertor._fromJSON:Z
#34 = Utf8 java/text/SimpleDateFormat
#35 = Class #34 // java/text/SimpleDateFormat
#36 = Methodref #35.#24 // java/text/SimpleDateFormat."<init>":(Ljava/lang/String;)V
#37 = NameAndType #9:#10 // _format:Ljava/text/SimpleDateFormat;
#38 = Fieldref #2.#37 // org/mortbay/util/ajax/JSONDateConvertor._format:Ljava/text/SimpleDateFormat;
#39 = Methodref #35.#30 // java/text/SimpleDateFormat.setTimeZone:(Ljava/util/TimeZone;)V
#40 = Utf8 (Ljava/lang/String;Ljava/util/TimeZone;ZLjava/util/Locale;)V
#41 = Utf8 (Ljava/lang/String;Ljava/util/Locale;)V
#42 = NameAndType #13:#41 // "<init>":(Ljava/lang/String;Ljava/util/Locale;)V
#43 = Methodref #22.#42 // org/mortbay/util/DateCache."<init>":(Ljava/lang/String;Ljava/util/Locale;)V
#44 = Utf8 java/text/DateFormatSymbols
#45 = Class #44 // java/text/DateFormatSymbols
#46 = Utf8 (Ljava/util/Locale;)V
#47 = NameAndType #13:#46 // "<init>":(Ljava/util/Locale;)V
#48 = Methodref #45.#47 // java/text/DateFormatSymbols."<init>":(Ljava/util/Locale;)V
#49 = Utf8 (Ljava/lang/String;Ljava/text/DateFormatSymbols;)V
#50 = NameAndType #13:#49 // "<init>":(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V
#51 = Methodref #35.#50 // java/text/SimpleDateFormat."<init>":(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V
#52 = Utf8 DEFAULT_FORMAT
#53 = Utf8 Ljava/lang/String;
#54 = NameAndType #52:#53 // DEFAULT_FORMAT:Ljava/lang/String;
#55 = Fieldref #22.#54 // org/mortbay/util/DateCache.DEFAULT_FORMAT:Ljava/lang/String;
#56 = Utf8 GMT
#57 = String #56 // GMT
#58 = Utf8 java/util/TimeZone
#59 = Class #58 // java/util/TimeZone
#60 = Utf8 getTimeZone
#61 = Utf8 (Ljava/lang/String;)Ljava/util/TimeZone;
#62 = NameAndType #60:#61 // getTimeZone:(Ljava/lang/String;)Ljava/util/TimeZone;
#63 = Methodref #59.#62 // java/util/TimeZone.getTimeZone:(Ljava/lang/String;)Ljava/util/TimeZone;
#64 = NameAndType #13:#18 // "<init>":(Ljava/lang/String;Ljava/util/TimeZone;Z)V
#65 = Methodref #2.#64 // org/mortbay/util/ajax/JSONDateConvertor."<init>":(Ljava/lang/String;Ljava/util/TimeZone;Z)V
#66 = Utf8 fromJSON
#67 = Utf8 (Ljava/util/Map;)Ljava/lang/Object;
#68 = Utf8 java/lang/UnsupportedOperationException
#69 = Class #68 // java/lang/UnsupportedOperationException
#70 = Methodref #69.#19 // java/lang/UnsupportedOperationException."<init>":()V
#71 = Utf8 value
#72 = String #71 // value
#73 = Utf8 java/util/Map
#74 = Class #73 // java/util/Map
#75 = Utf8 get
#76 = Utf8 (Ljava/lang/Object;)Ljava/lang/Object;
#77 = NameAndType #75:#76 // get:(Ljava/lang/Object;)Ljava/lang/Object;
#78 = InterfaceMethodref #74.#77 // java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
#79 = Utf8 java/lang/String
#80 = Class #79 // java/lang/String
#81 = Utf8 parseObject
#82 = Utf8 (Ljava/lang/String;)Ljava/lang/Object;
#83 = NameAndType #81:#82 // parseObject:(Ljava/lang/String;)Ljava/lang/Object;
#84 = Methodref #35.#83 // java/text/SimpleDateFormat.parseObject:(Ljava/lang/String;)Ljava/lang/Object;
#85 = Utf8 org/mortbay/log/Log
#86 = Class #85 // org/mortbay/log/Log
#87 = Utf8 warn
#88 = Utf8 (Ljava/lang/Throwable;)V
#89 = NameAndType #87:#88 // warn:(Ljava/lang/Throwable;)V
#90 = Methodref #86.#89 // org/mortbay/log/Log.warn:(Ljava/lang/Throwable;)V
#91 = Utf8 java/lang/Exception
#92 = Class #91 // java/lang/Exception
#93 = Utf8 toJSON
#94 = Utf8 (Ljava/lang/Object;Lorg/mortbay/util/ajax/JSON$Output;)V
#95 = Utf8 java/util/Date
#96 = Class #95 // java/util/Date
#97 = Utf8 format
#98 = Utf8 (Ljava/util/Date;)Ljava/lang/String;
#99 = NameAndType #97:#98 // format:(Ljava/util/Date;)Ljava/lang/String;
#100 = Methodref #22.#99 // org/mortbay/util/DateCache.format:(Ljava/util/Date;)Ljava/lang/String;
#101 = Utf8 getClass
#102 = Utf8 ()Ljava/lang/Class;
#103 = NameAndType #101:#102 // getClass:()Ljava/lang/Class;
#104 = Methodref #4.#103 // java/lang/Object.getClass:()Ljava/lang/Class;
#105 = Utf8 org/mortbay/util/ajax/JSON$Output
#106 = Class #105 // org/mortbay/util/ajax/JSON$Output
#107 = Utf8 addClass
#108 = Utf8 (Ljava/lang/Class;)V
#109 = NameAndType #107:#108 // addClass:(Ljava/lang/Class;)V
#110 = InterfaceMethodref #106.#109 // org/mortbay/util/ajax/JSON$Output.addClass:(Ljava/lang/Class;)V
#111 = Utf8 add
#112 = Utf8 (Ljava/lang/String;Ljava/lang/Object;)V
#113 = NameAndType #111:#112 // add:(Ljava/lang/String;Ljava/lang/Object;)V
#114 = InterfaceMethodref #106.#113 // org/mortbay/util/ajax/JSON$Output.add:(Ljava/lang/String;Ljava/lang/Object;)V
#115 = Utf8 (Ljava/lang/Object;)V
#116 = NameAndType #111:#115 // add:(Ljava/lang/Object;)V
#117 = InterfaceMethodref #106.#116 // org/mortbay/util/ajax/JSON$Output.add:(Ljava/lang/Object;)V
#118 = Utf8 Code
#119 = Utf8 LineNumberTable
{
org.mortbay.util.DateCache _dateCache;
descriptor: Lorg/mortbay/util/DateCache;
flags: (0x0000)
java.text.SimpleDateFormat _format;
descriptor: Ljava/text/SimpleDateFormat;
flags: (0x0000)
private boolean _fromJSON;
descriptor: Z
flags: (0x0002) ACC_PRIVATE
public org.mortbay.util.ajax.JSONDateConvertor();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: iconst_0
2: invokespecial #17 // Method "<init>":(Z)V
5: return
LineNumberTable:
line 43: 0
line 44: 5
public org.mortbay.util.ajax.JSONDateConvertor(java.lang.String, java.util.TimeZone, boolean);
descriptor: (Ljava/lang/String;Ljava/util/TimeZone;Z)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=4, args_size=4
0: aload_0
1: invokespecial #20 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #22 // class org/mortbay/util/DateCache
8: dup
9: aload_1
10: invokespecial #25 // Method org/mortbay/util/DateCache."<init>":(Ljava/lang/String;)V
13: putfield #27 // Field _dateCache:Lorg/mortbay/util/DateCache;
16: aload_0
17: getfield #27 // Field _dateCache:Lorg/mortbay/util/DateCache;
20: aload_2
21: invokevirtual #31 // Method org/mortbay/util/DateCache.setTimeZone:(Ljava/util/TimeZone;)V
24: aload_0
25: iload_3
26: putfield #33 // Field _fromJSON:Z
29: aload_0
30: new #35 // class java/text/SimpleDateFormat
33: dup
34: aload_1
35: invokespecial #36 // Method java/text/SimpleDateFormat."<init>":(Ljava/lang/String;)V
38: putfield #38 // Field _format:Ljava/text/SimpleDateFormat;
41: aload_0
42: getfield #38 // Field _format:Ljava/text/SimpleDateFormat;
45: aload_2
46: invokevirtual #39 // Method java/text/SimpleDateFormat.setTimeZone:(Ljava/util/TimeZone;)V
49: return
LineNumberTable:
line 52: 0
line 53: 4
line 54: 16
line 55: 24
line 56: 29
line 57: 41
line 58: 49
public org.mortbay.util.ajax.JSONDateConvertor(java.lang.String, java.util.TimeZone, boolean, java.util.Locale);
descriptor: (Ljava/lang/String;Ljava/util/TimeZone;ZLjava/util/Locale;)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=7, locals=5, args_size=5
0: aload_0
1: invokespecial #20 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #22 // class org/mortbay/util/DateCache
8: dup
9: aload_1
10: aload 4
12: invokespecial #43 // Method org/mortbay/util/DateCache."<init>":(Ljava/lang/String;Ljava/util/Locale;)V
15: putfield #27 // Field _dateCache:Lorg/mortbay/util/DateCache;
18: aload_0
19: getfield #27 // Field _dateCache:Lorg/mortbay/util/DateCache;
22: aload_2
23: invokevirtual #31 // Method org/mortbay/util/DateCache.setTimeZone:(Ljava/util/TimeZone;)V
26: aload_0
27: iload_3
28: putfield #33 // Field _fromJSON:Z
31: aload_0
32: new #35 // class java/text/SimpleDateFormat
35: dup
36: aload_1
37: new #45 // class java/text/DateFormatSymbols
40: dup
41: aload 4
43: invokespecial #48 // Method java/text/DateFormatSymbols."<init>":(Ljava/util/Locale;)V
46: invokespecial #51 // Method java/text/SimpleDateFormat."<init>":(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V
49: putfield #38 // Field _format:Ljava/text/SimpleDateFormat;
52: aload_0
53: getfield #38 // Field _format:Ljava/text/SimpleDateFormat;
56: aload_2
57: invokevirtual #39 // Method java/text/SimpleDateFormat.setTimeZone:(Ljava/util/TimeZone;)V
60: return
LineNumberTable:
line 61: 0
line 62: 4
line 63: 18
line 64: 26
line 65: 31
line 66: 52
line 67: 60
public org.mortbay.util.ajax.JSONDateConvertor(boolean);
descriptor: (Z)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
0: aload_0
1: getstatic #55 // Field org/mortbay/util/DateCache.DEFAULT_FORMAT:Ljava/lang/String;
4: ldc #57 // String GMT
6: invokestatic #63 // Method java/util/TimeZone.getTimeZone:(Ljava/lang/String;)Ljava/util/TimeZone;
9: iload_1
10: invokespecial #65 // Method "<init>":(Ljava/lang/String;Ljava/util/TimeZone;Z)V
13: return
LineNumberTable:
line 48: 0
line 49: 13
public java.lang.Object fromJSON(java.util.Map);
descriptor: (Ljava/util/Map;)Ljava/lang/Object;
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=3, args_size=2
0: aload_0
1: getfield #33 // Field _fromJSON:Z
4: ifne 15
7: new #69 // class java/lang/UnsupportedOperationException
10: dup
11: invokespecial #70 // Method java/lang/UnsupportedOperationException."<init>":()V
14: athrow
15: aload_0
16: getfield #38 // Field _format:Ljava/text/SimpleDateFormat;
19: astore_2
20: aload_2
21: monitorenter
22: aload_0
23: getfield #38 // Field _format:Ljava/text/SimpleDateFormat;
26: aload_1
27: ldc #72 // String value
29: invokeinterface #78, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
34: checkcast #80 // class java/lang/String
37: invokevirtual #84 // Method java/text/SimpleDateFormat.parseObject:(Ljava/lang/String;)Ljava/lang/Object;
40: astore_1
41: aload_2
42: monitorexit
43: aload_1
44: areturn
45: astore_1
46: aload_2
47: monitorexit
48: aload_1
49: athrow
50: astore_1
51: aload_1
52: invokestatic #90 // Method org/mortbay/log/Log.warn:(Ljava/lang/Throwable;)V
55: aconst_null
56: astore_1
57: goto 43
Exception table:
from to target type
15 22 50 Class java/lang/Exception
22 43 45 any
46 48 45 any
48 50 50 Class java/lang/Exception
LineNumberTable:
line 71: 0
line 72: 7
line 75: 15
line 77: 22
line 84: 43
line 78: 45
line 80: 50
line 82: 51
line 84: 55
public void toJSON(java.lang.Object, org.mortbay.util.ajax.JSON$Output);
descriptor: (Ljava/lang/Object;Lorg/mortbay/util/ajax/JSON$Output;)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=3, locals=4, args_size=3
0: aload_0
1: getfield #27 // Field _dateCache:Lorg/mortbay/util/DateCache;
4: aload_1
5: checkcast #96 // class java/util/Date
8: invokevirtual #100 // Method org/mortbay/util/DateCache.format:(Ljava/util/Date;)Ljava/lang/String;
11: astore_3
12: aload_0
13: getfield #33 // Field _fromJSON:Z
16: ifeq 39
19: aload_2
20: aload_1
21: invokevirtual #104 // Method java/lang/Object.getClass:()Ljava/lang/Class;
24: invokeinterface #110, 2 // InterfaceMethod org/mortbay/util/ajax/JSON$Output.addClass:(Ljava/lang/Class;)V
29: aload_2
30: ldc #72 // String value
32: aload_3
33: invokeinterface #114, 3 // InterfaceMethod org/mortbay/util/ajax/JSON$Output.add:(Ljava/lang/String;Ljava/lang/Object;)V
38: return
39: aload_2
40: aload_3
41: invokeinterface #117, 2 // InterfaceMethod org/mortbay/util/ajax/JSON$Output.add:(Ljava/lang/Object;)V
46: goto 38
LineNumberTable:
line 89: 0
line 90: 12
line 92: 19
line 93: 29
line 99: 38
line 97: 39
}
Use the following class and analyze it using:
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.BasicVerifier;
import org.objectweb.asm.util.CheckClassAdapter;
public class Test {
public static void main(String[] args) throws Throwable {
ClassReader cr = new ClassReader(Files.newInputStream(Paths.get("JSONDateConvertor.class")));
ClassNode cn = new ClassNode();
cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
List<MethodNode> methods = cn.methods;
for (MethodNode method : methods) {
BasicVerifier verifier = new BasicVerifier();
Analyzer<BasicValue> a = new Analyzer<>(verifier);
a.analyze(cn.name, method);
}
}
}
This yields the following exception:
Exception in thread "main" org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 30: Expected an object reference, but found .
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:275)
at Test.main(Test.java:26)
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Expected an object reference, but found .
at org.objectweb.asm.tree.analysis.BasicVerifier.copyOperation(BasicVerifier.java:90)
at org.objectweb.asm.tree.analysis.BasicVerifier.copyOperation(BasicVerifier.java:44)
at org.objectweb.asm.tree.analysis.Frame.execute(Frame.java:326)
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:171)
... 1 more
Closes #318009
Eric Bruneton (bde266f0) at 21 Dec 12:17
Merge branch '318009-fix-analyzer-regression' into 'master'
... and 1 more commit
Thanks. I was not completely sure of the optimization for the instructions other than the last one in a try-catch range, so I removed it.
Eric Bruneton (7a5bdbf2) at 21 Dec 12:07
Always merge the frame before and after an instruction I in a try-c...
Closes #318009
Eric Bruneton (6d161c5d) at 20 Dec 14:00
ASM Analyzer: fix regression introduced in fix of bug #317991.
LGTM
LGTM
LGTM
LGTM
'nextLocal' might be a better name.
Can you use a lambda to avoid duplicating this block below?
Nit: I would put this method after generateConcatMethod.
Nit: missing final dot.