Skip to content

Commit f6b125c

Browse files
davidpichardiefacebook-github-bot
authored andcommitted
Fixing unsound old devirtualization performed in Java frontend
Summary: The java frontend used an unsound flow insensitive class analysis to devirtualize some virtual calls. We remove it and let the recent devirtualizer preanalysis do the job. This unsoudness in the Java frontend may have been here for a long time. Removing it may modify several analysis results (specially Nullsafe) where virtual calls may look different now. Reviewed By: jvillard Differential Revision: D22662739 fbshipit-source-id: c45296dce
1 parent 2547a75 commit f6b125c

File tree

7 files changed

+13
-39
lines changed

7 files changed

+13
-39
lines changed

infer/src/java/jTrans.ml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,17 +1070,7 @@ let instruction (context : JContext.t) pc instr : translation =
10701070
let call_node = create_node node_kind (instrs @ call_instrs) in
10711071
call_node
10721072
in
1073-
let trans_virtual_call original_cn invoke_kind =
1074-
let cn' =
1075-
match JTransType.extract_cn_no_obj sil_obj_type with
1076-
| Some cn ->
1077-
cn
1078-
| None ->
1079-
original_cn
1080-
in
1081-
let call_node = create_call_node cn' invoke_kind in
1082-
Instr call_node
1083-
in
1073+
let trans_virtual_call cn invoke_kind = Instr (create_call_node cn invoke_kind) in
10841074
match call_kind with
10851075
| JBir.VirtualCall obj_type ->
10861076
let cn =

infer/src/java/jTransType.ml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,6 @@ let rec create_array_type typ dim =
7171
else typ
7272

7373

74-
let extract_cn_no_obj (typ : Typ.t) =
75-
match typ.desc with
76-
| Tptr ({desc= Tstruct (JavaClass _ as name)}, Pk_pointer) ->
77-
let class_name = JBasics.make_cn (Typ.Name.name name) in
78-
if JBasics.cn_equal class_name JBasics.java_lang_object then None else Some class_name
79-
| _ ->
80-
None
81-
82-
8374
(** Printing types *)
8475
let object_type_to_string ot =
8576
let rec array_type_to_string (vt : JBasics.value_type) =

infer/src/java/jTransType.mli

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,5 @@ val package_to_string : string list -> string option
6464
val create_array_type : Typ.t -> int -> Typ.t
6565
(** [create_array_type typ dim] creates an array type with dimension dim and content typ *)
6666

67-
val extract_cn_no_obj : Typ.t -> JBasics.class_name option
68-
(** [extract_cn_type_np] returns the Java class name of typ when typ is a pointer type, otherwise
69-
returns None *)
70-
7167
val object_type_to_string : JBasics.object_type -> string
7268
(** returns a string representation of an object Java type *)

infer/tests/codetoanalyze/java/biabduction/ReaderLeaks.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public void readerNotClosedAfterRead() {
3434
}
3535
}
3636

37-
public void readerClosed() throws IOException {
37+
public void readerClosed_FP() throws IOException {
3838
Reader r = null;
3939
try {
4040
r = new FileReader("testing.txt");

infer/tests/codetoanalyze/java/biabduction/issues.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.Reader
137137
codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.pipedReaderNotClosedAfterConnect(java.io.PipedWriter):void, 7, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure pipedReaderNotClosedAfterConnect(...),exception java.io.IOException]
138138
codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.pipedReaderNotClosedAfterConstructedWithWriter():void, 8, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure pipedReaderNotClosedAfterConstructedWithWriter(),exception java.io.IOException]
139139
codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.pushbackReaderNotClosedAfterRead():void, 6, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure pushbackReaderNotClosedAfterRead(),Skipping PushbackReader(...): unknown method,exception java.io.IOException]
140+
codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.readerClosed_FP():void, 8, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure readerClosed_FP(),Skipping FileReader(...): unknown method,exception java.io.IOException,Switch condition is true. Entering switch case,Taking true branch]
140141
codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.readerNotClosedAfterRead():void, 6, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure readerNotClosedAfterRead(),Skipping FileReader(...): unknown method,exception java.io.IOException]
141142
codetoanalyze/java/biabduction/ResourceLeaks.java, codetoanalyze.java.infer.ResourceLeaks.NoResourceLeakWarningAfterCheckState(java.io.File,int):void, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure NoResourceLeakWarningAfterCheckState(...),Taking false branch]
142143
codetoanalyze/java/biabduction/ResourceLeaks.java, codetoanalyze.java.infer.ResourceLeaks.activityObtainTypedArrayAndLeak(android.app.Activity):void, 2, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure activityObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]

infer/tests/codetoanalyze/java/pulse/DefaultInInterface.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,19 @@ public void overridenCallNPE() {
4545
}
4646
}
4747

48-
static void FN_uncertainCallNPE(int i) {
49-
A firstAthenB = new A();
48+
static void uncertainCallMethod1NPE(int i) {
49+
A aAorB = new A();
5050
if (i > 0) { // feasible path
51-
firstAthenB = new B();
51+
aAorB = new B();
5252
}
53-
System.out.println(firstAthenB.defaultMethod1().toString());
53+
System.out.println(aAorB.defaultMethod1().toString());
5454
}
5555

56-
static boolean alwaysFalse() {
57-
return false;
58-
}
59-
60-
static void FP_uncertainCallOk(int i) {
61-
A firstAthenB = new A();
62-
if (alwaysFalse()) { // unfeasible path
63-
firstAthenB = new B();
56+
static void FN_uncertainCallMethod2NPE(int i) {
57+
A aAorB = new A();
58+
if (i > 0) { // feasible path
59+
aAorB = new B();
6460
}
65-
System.out.println(firstAthenB.defaultMethod2().toString());
61+
System.out.println(aAorB.defaultMethod2().toString());
6662
}
6763
}

infer/tests/codetoanalyze/java/pulse/issues.exp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
codetoanalyze/java/pulse/DefaultInInterface.java, DefaultInInterface$A.defaultCallNPE():void, 1, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DefaultInInterface$I.defaultMethod1()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DefaultInInterface$I.defaultMethod1()`,return from call to `Object DefaultInInterface$I.defaultMethod1()`,assigned,invalid access occurs here]
22
codetoanalyze/java/pulse/DefaultInInterface.java, DefaultInInterface$B.overridenCallNPE():void, 1, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DefaultInInterface$B.defaultMethod2()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DefaultInInterface$B.defaultMethod2()`,return from call to `Object DefaultInInterface$B.defaultMethod2()`,assigned,invalid access occurs here]
3-
codetoanalyze/java/pulse/DefaultInInterface.java, DefaultInInterface.FP_uncertainCallOk(int):void, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DefaultInInterface$B.defaultMethod2()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DefaultInInterface$B.defaultMethod2()`,return from call to `Object DefaultInInterface$B.defaultMethod2()`,assigned,invalid access occurs here]
3+
codetoanalyze/java/pulse/DefaultInInterface.java, DefaultInInterface.uncertainCallMethod1NPE(int):void, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DefaultInInterface$I.defaultMethod1()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DefaultInInterface$I.defaultMethod1()`,return from call to `Object DefaultInInterface$I.defaultMethod1()`,assigned,invalid access occurs here]
44
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch$WithField.dispatchOnFieldOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Supertype.bar()`,return from call to `Object DynamicDispatch$Supertype.bar()`,assigned,invalid access occurs here]
55
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSubtypeOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]
66
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSupertypeBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]

0 commit comments

Comments
 (0)