Effective Soundness-Guided Reflection Analysis
Yue Li, Tian Tan and Jingling Xue
Complier Research Group @ UNSW, Australia September 10, 2015
Effective Soundness-Guided Reflection Analysis Yue Li , Tian Tan and - - PowerPoint PPT Presentation
Effective Soundness-Guided Reflection Analysis Yue Li , Tian Tan and Jingling Xue Complier Research Group @ UNSW, Australia September 10, 2015 SAS 2015 Saint-Malo Static analysis for OO in practice ? Static analysis for OO in practice ? re re
Complier Research Group @ UNSW, Australia September 10, 2015
1
1
1
2
1
2
1
2
1
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
A a = (A) v2
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
A a = (A) v2
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
A a = (A) v2
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
A a = (A) v2
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
B b = (B) v2 A a = (A) v1
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
B b = (B) v2 A a = (A) v1
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
B b = (B) v2 A a = (A) v1 m1.invoke(v3, args)
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
B b = (B) v2 A a = (A) v1 m1.invoke(v3, args)
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
B b = (B) v2 A a = (A) v1 m1.invoke(v3, args)
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
B | | i | v3
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
B | | i | v3
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
B | | i | v3
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
| B | i | b, v3
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
B | | i | v3
i
| B | i | b, v4
i
| B | i | b
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
| B | i | b, v3
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
1
2
2 If the information in a program is not enough to help infer the reflective targets, the soundness criteria is not satisfied
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v3
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v3
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v3
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v3
Class c = Class.forName(cName)
Object v = c1.newInstance( )
i:
unknown
i
Abstract Heap Objects
are created lazily ( at LHM points )
i
A | i | | a |
Type Object Location
|
Pointed by
|
Method m = c2.getDeclaredMethod(mName, ...)
i
D | | i | v3 B b = (B) v2 A a = (A) v1 m1.invoke(v3, args) v3.mName(args)
i
| B | i | b, v3
2 If the information in a program is not enough to help infer the reflective targets, the soundness criteria is not satisfied The number of the reflective targets resolved or inferred
1
2
1 Recall: measured by the number of true reflective targets discovered at reflective call sites that are dynamically executed under certain inputs
1 Only Solar achieves total recall : all the true reflective targets found in recall are resolved by Solar. Recall: measured by the number of true reflective targets discovered at reflective call sites that are dynamically executed under certain inputs
The benefit of achieving higher recall: more true call graph edges discovered
The benefit of achieving higher recall: more true call graph edges discovered The figure shows the more true call graph edges found in recall by Solar than Elf (Solar - Elf) and by Elf than Doop (Elf - Doop) The true call graph edges are computed by instrumentation at runtime
1 Insight: Soundness ßà precision. Solar achieves higher recall (more sound), indicates worse precision ?
1 Insight: Soundness ßà precision. Solar achieves higher recall (more sound), indicates worse precision ? No! Solar maintains nearly the same precision as Doop and Elf (2 popular clients).
Devir Call: the percentage of the virtual calls whose targets can be disambiguated Safe Case: the percentage of the casts that can be statically shown to be safe
2
In 10 evaluated programs, 7 can be analyzed scalably and soundly by Solar with full automation.
2
In 10 evaluated programs, 7 can be analyzed scalably and soundly by Solar with full automation. For the remaining 3 programs, Probe is scalable and reports 13 unsound calls and 1 imprecise call.
2
In 10 evaluated programs, 7 can be analyzed scalably and soundly by Solar with full automation.
2 After manual check, all the identified 14 unsound/imprecise calls are the true ones. For the remaining 3 programs, Probe is scalable and reports 13 unsound calls and 1 imprecise call.
In 10 evaluated programs, 7 can be analyzed scalably and soundly by Solar with full automation.
2 After manual check, all the identified 14 unsound/imprecise calls are the true ones. Probe also reports 7 corresponding annotation points for these 14 unsound/imprecise calls For the remaining 3 programs, Probe is scalable and reports 13 unsound calls and 1 imprecise call.
In 10 evaluated programs, 7 can be analyzed scalably and soundly by Solar with full automation.
2 After manual check, all the identified 14 unsound/imprecise calls are the true ones. Probe also reports 7 corresponding annotation points for these 14 unsound/imprecise calls After the 7 light-weight annotations, Solar can analyze these 3 programs scalably and soundly For the remaining 3 programs, Probe is scalable and reports 13 unsound calls and 1 imprecise call.
1
2
1
Reflection Analysis
Hundreds of Papers & Tools ¡
1
Reflection Analysis
Hundreds of Papers & Tools ¡
1
Reflection Analysis
Hundreds of Papers & Tools ¡
Nothing needs to change
1
Reflection Analysis
Hundreds of Papers & Tools ¡
Nothing needs to change More bugs, etc.
4 reflective calls are identified unsoundly analyzed by Solar
1 Hundreds of Papers & Tools ¡
Reflection Analysis
Nothing needs to change More bugs, etc.
2
All reflective calls are reported soundly analyzed by Solar 4 reflective calls are identified unsoundly analyzed by Solar
1 Hundreds of Papers & Tools ¡
Reflection Analysis
Nothing needs to change More bugs, etc.
2
h#p://www.cse.unsw.edu.au/~corg/solar ¡
September 10, 2015
CORG @ UNSW, Australia
2
1 The number of annotations required for improving the soundness of unsoundly resolved reflective calls. Others: 338 vs Solar: 7