[infer][biabduction] fix the dynamic resolution of non virtual calls

Summary: The resolution was previously only happening for constructors, but calls to private methods or to `super` are also neither static calls nor virtual calls. In this case, the resolution logic should be the same as for constructors.

Reviewed By: sblackshear

Differential Revision: D5830376

fbshipit-source-id: 9b56f80
master
Jeremy Dubreil 7 years ago committed by Facebook Github Bot
parent ca3e454481
commit 42fc24ebfd

@ -659,23 +659,23 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Typ.Procna
(** Resolve the name of the procedure to call based on the type of the arguments *)
let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.java =
let resolve_from_args resolved_pname_java args =
let parameters = Typ.Procname.java_get_parameters resolved_pname_java in
if List.length args <> List.length parameters then resolved_pname_java
else
let resolved_params =
List.fold2_exn
~f:(fun accu (arg_exp, _) name ->
match resolve_typename prop arg_exp with
| Some class_name
-> Typ.Procname.split_classname (Typ.Name.name class_name) :: accu
| None
-> name :: accu)
~init:[] args (Typ.Procname.java_get_parameters resolved_pname_java)
|> List.rev
in
Typ.Procname.java_replace_parameters resolved_pname_java resolved_params
let resolved_params =
List.fold2_exn
~f:(fun accu (arg_exp, _) name ->
match resolve_typename prop arg_exp with
| Some class_name
-> Typ.Procname.split_classname (Typ.Name.name class_name) :: accu
| None
-> name :: accu)
~init:[] args (Typ.Procname.java_get_parameters resolved_pname_java)
|> List.rev
in
Typ.Procname.java_replace_parameters resolved_pname_java resolved_params
in
let resolved_pname_java, other_args =
let pname = Typ.Procname.Java pname_java
and parameters = Typ.Procname.java_get_parameters pname_java in
let match_parameters args = Int.equal (List.length args) (List.length parameters) in
match args with
| []
-> (pname_java, [])
@ -683,7 +683,7 @@ let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.java
-> let resolved =
match resolve_typename prop first_arg with
| Some class_name -> (
match resolve_method tenv class_name (Typ.Procname.Java pname_java) with
match resolve_method tenv class_name pname with
| Typ.Procname.Java resolved_pname_java
-> resolved_pname_java
| _
@ -692,10 +692,15 @@ let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.java
-> pname_java
in
(resolved, other_args)
| _ :: other_args when Typ.Procname.is_constructor (Typ.Procname.Java pname_java)
| _ :: other_args
when match_parameters other_args (* Non-virtual call, e.g. constructors or private methods *)
-> (pname_java, other_args)
| args
| args when match_parameters args (* Static call *)
-> (pname_java, args)
| args
-> L.(die InternalError)
"Call mismatch: method %a has %i paramters but is called with %i arguments@."
Typ.Procname.pp pname (List.length parameters) (List.length args)
in
resolve_from_args resolved_pname_java other_args

@ -31,6 +31,7 @@ codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispa
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchCallsWrapperWithSupertypeBad(), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchCallsWrapperWithSupertypeBad(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),start of procedure dynamicDispatchWrapperBar(...),start of procedure bar(),return from a call to Object DynamicDispatch$Supertype.bar(),return from a call to Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchShouldNotCauseFalseNegativeEasy(), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchShouldNotCauseFalseNegativeEasy(),start of procedure DynamicDispatch$Subtype(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),return from a call to DynamicDispatch$Subtype.<init>(),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchShouldNotReportWhenCallingSupertype(DynamicDispatch$Subtype), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchShouldNotReportWhenCallingSupertype(...),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicResolutionWithPrivateMethodBad(), 2, NULL_DEREFERENCE, [start of procedure dynamicResolutionWithPrivateMethodBad(),start of procedure DynamicDispatch$Subtype(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),return from a call to DynamicDispatch$Subtype.<init>(),start of procedure callFoo(...),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo(),return from a call to Object DynamicDispatch.callFoo(DynamicDispatch$Subtype)]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.interfaceShouldNotCauseFalseNegativeEasy(), 3, NULL_DEREFERENCE, [start of procedure interfaceShouldNotCauseFalseNegativeEasy(),start of procedure DynamicDispatch$Impl(),return from a call to DynamicDispatch$Impl.<init>(),start of procedure foo(),return from a call to Object DynamicDispatch$Impl.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.interfaceShouldNotCauseFalseNegativeHard(DynamicDispatch$Impl), 1, NULL_DEREFERENCE, [start of procedure interfaceShouldNotCauseFalseNegativeHard(...),start of procedure foo(),return from a call to Object DynamicDispatch$Impl.foo()]
codetoanalyze/java/infer/FilterInputStreamLeaks.java, void FilterInputStreamLeaks.bufferedInputStreamNotClosedAfterRead(), 7, RESOURCE_LEAK, [start of procedure bufferedInputStreamNotClosedAfterRead(),Skipping BufferedInputStream(...): unknown method,exception java.io.IOException]
@ -133,8 +134,8 @@ codetoanalyze/java/infer/ResourceLeaks.java, boolean ResourceLeaks.jarFileNotClo
codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.fileOutputStreamTwoLeaks1(boolean), 3, RESOURCE_LEAK, [start of procedure fileOutputStreamTwoLeaks1(...),Taking true branch]
codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.fileOutputStreamTwoLeaks1(boolean), 6, RESOURCE_LEAK, [start of procedure fileOutputStreamTwoLeaks1(...),Taking false branch]
codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.readConfigNotCloseStream(String), 5, RESOURCE_LEAK, [start of procedure readConfigNotCloseStream(...)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.activityObtainTypedArrayAndLeak(Activity), 2, RESOURCE_LEAK, [start of procedure activityObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.contextObtainTypedArrayAndLeak(Context), 2, RESOURCE_LEAK, [start of procedure contextObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.activityObtainTypedArrayAndLeak(Activity), 2, RESOURCE_LEAK, [start of procedure activityObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.contextObtainTypedArrayAndLeak(Context), 2, RESOURCE_LEAK, [start of procedure contextObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.copyFileLeak(File,File), 11, RESOURCE_LEAK, [start of procedure copyFileLeak(...),Skipping transferTo(...): unknown method,Taking true branch,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.copyFileLeak(File,File), 11, RESOURCE_LEAK, [start of procedure copyFileLeak(...),exception java.io.FileNotFoundException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.deflaterLeak(), 1, RESOURCE_LEAK, [start of procedure deflaterLeak()]
@ -166,7 +167,7 @@ codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.pipedOutputStrea
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.scannerNotClosed(), 1, RESOURCE_LEAK, [start of procedure scannerNotClosed()]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.serverSocketNotClosed(), 12, RESOURCE_LEAK, [start of procedure serverSocketNotClosed(),Skipping ServerSocket(...): unknown method,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.socketNotClosed(), 1, RESOURCE_LEAK, [start of procedure socketNotClosed()]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.themeObtainTypedArrayAndLeak(Resources$Theme), 2, RESOURCE_LEAK, [start of procedure themeObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.themeObtainTypedArrayAndLeak(Resources$Theme), 2, RESOURCE_LEAK, [start of procedure themeObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.twoResourcesRandomAccessFile(), 10, RESOURCE_LEAK, [start of procedure twoResourcesRandomAccessFile(),Taking true branch,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.zipFileLeakExceptionalBranch(), 5, RESOURCE_LEAK, [start of procedure zipFileLeakExceptionalBranch(),exception java.io.IOException,Switch condition is true. Entering switch case]

@ -133,4 +133,26 @@ public class DynamicDispatch {
}
private Object callFoo(Supertype o) {
return o.foo();
}
void dynamicResolutionWithPrivateMethodBad() {
Supertype subtype = new Subtype();
callFoo(subtype).toString();
}
Object variadicMethod(Supertype... args) {
if (args.length == 0) {
return null;
} else {
return args[0].foo();
}
}
void dynamicResolutionWithVariadicMethodBad() {
Supertype subtype = new Subtype();
variadicMethod(subtype, null, null).toString();
}
}

@ -53,6 +53,7 @@ codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispa
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchCallsWrapperWithSupertypeBad(), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchCallsWrapperWithSupertypeBad(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),start of procedure dynamicDispatchWrapperBar(...),start of procedure bar(),return from a call to Object DynamicDispatch$Supertype.bar(),return from a call to Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchShouldNotCauseFalseNegativeEasy(), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchShouldNotCauseFalseNegativeEasy(),start of procedure DynamicDispatch$Subtype(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),return from a call to DynamicDispatch$Subtype.<init>(),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicDispatchShouldNotReportWhenCallingSupertype(DynamicDispatch$Subtype), 3, NULL_DEREFERENCE, [start of procedure dynamicDispatchShouldNotReportWhenCallingSupertype(...),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.dynamicResolutionWithPrivateMethodBad(), 2, NULL_DEREFERENCE, [start of procedure dynamicResolutionWithPrivateMethodBad(),start of procedure DynamicDispatch$Subtype(),start of procedure DynamicDispatch$Supertype(),return from a call to DynamicDispatch$Supertype.<init>(),return from a call to DynamicDispatch$Subtype.<init>(),start of procedure callFoo(...),start of procedure foo(),return from a call to Object DynamicDispatch$Subtype.foo(),return from a call to Object DynamicDispatch.callFoo(DynamicDispatch$Subtype)]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.interfaceShouldNotCauseFalseNegativeEasy(), 3, NULL_DEREFERENCE, [start of procedure interfaceShouldNotCauseFalseNegativeEasy(),start of procedure DynamicDispatch$Impl(),return from a call to DynamicDispatch$Impl.<init>(),start of procedure foo(),return from a call to Object DynamicDispatch$Impl.foo()]
codetoanalyze/java/infer/DynamicDispatch.java, void DynamicDispatch.interfaceShouldNotCauseFalseNegativeHard(DynamicDispatch$Impl), 1, NULL_DEREFERENCE, [start of procedure interfaceShouldNotCauseFalseNegativeHard(...),start of procedure foo(),return from a call to Object DynamicDispatch$Impl.foo()]
codetoanalyze/java/infer/FilterInputStreamLeaks.java, void FilterInputStreamLeaks.bufferedInputStreamNotClosedAfterRead(), 7, RESOURCE_LEAK, [start of procedure bufferedInputStreamNotClosedAfterRead(),Skipping BufferedInputStream(...): unknown method,exception java.io.IOException]
@ -163,13 +164,13 @@ codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.readConfigCloseSt
codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.readConfigNotCloseStream(String), 5, RESOURCE_LEAK, [start of procedure readConfigNotCloseStream(...)]
codetoanalyze/java/infer/ResourceLeaks.java, int ResourceLeaks.tryWithResource(), 3, UNINITIALIZED_VALUE, [start of procedure tryWithResource(),exception java.io.IOException,Switch condition is true. Entering switch case,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.NoResourceLeakWarningAfterCheckState(File,int), 2, PRECONDITION_NOT_MET, [start of procedure NoResourceLeakWarningAfterCheckState(...),Taking false branch]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.activityObtainTypedArrayAndLeak(Activity), 2, RESOURCE_LEAK, [start of procedure activityObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.activityObtainTypedArrayAndLeak(Activity), 2, RESOURCE_LEAK, [start of procedure activityObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.closeNullQuietlyWithCloseables(), 5, UNINITIALIZED_VALUE, [start of procedure closeNullQuietlyWithCloseables(),exception java.io.FileNotFoundException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.closeNullWithCloseables(), 5, UNINITIALIZED_VALUE, [start of procedure closeNullWithCloseables(),exception java.io.FileNotFoundException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.closeWithCloseablesNestedAlloc(), 5, UNINITIALIZED_VALUE, [start of procedure closeWithCloseablesNestedAlloc(),exception java.io.FileNotFoundException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.closedQuietlyWithCloseables(), 5, UNINITIALIZED_VALUE, [start of procedure closedQuietlyWithCloseables(),exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.closedWithCloseables(), 5, UNINITIALIZED_VALUE, [start of procedure closedWithCloseables(),exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.contextObtainTypedArrayAndLeak(Context), 2, RESOURCE_LEAK, [start of procedure contextObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.contextObtainTypedArrayAndLeak(Context), 2, RESOURCE_LEAK, [start of procedure contextObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.copyFileLeak(File,File), 6, UNINITIALIZED_VALUE, [start of procedure copyFileLeak(...),exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.copyFileLeak(File,File), 11, RESOURCE_LEAK, [start of procedure copyFileLeak(...),Skipping transferTo(...): unknown method,Taking true branch,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.copyFileLeak(File,File), 11, RESOURCE_LEAK, [start of procedure copyFileLeak(...),exception java.io.FileNotFoundException]
@ -204,7 +205,7 @@ codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.scannerNotClosed
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.serverSocketNotClosed(), 12, RESOURCE_LEAK, [start of procedure serverSocketNotClosed(),Skipping ServerSocket(...): unknown method,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.serverSocketWithSocketClosed(), 14, UNINITIALIZED_VALUE, [start of procedure serverSocketWithSocketClosed(),Skipping ServerSocket(...): unknown method,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.socketNotClosed(), 1, RESOURCE_LEAK, [start of procedure socketNotClosed()]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.themeObtainTypedArrayAndLeak(Resources$Theme), 2, RESOURCE_LEAK, [start of procedure themeObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(Object)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.themeObtainTypedArrayAndLeak(Resources$Theme), 2, RESOURCE_LEAK, [start of procedure themeObtainTypedArrayAndLeak(...),start of procedure ignore(...),return from a call to void ResourceLeaks.ignore(TypedArray)]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.twoResources(), 8, UNINITIALIZED_VALUE, [start of procedure twoResources(),exception java.io.FileNotFoundException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.twoResources(), 11, RESOURCE_LEAK, [start of procedure twoResources(),Taking true branch,exception java.io.IOException]
codetoanalyze/java/infer/ResourceLeaks.java, void ResourceLeaks.twoResourcesCommonFix(), 8, UNINITIALIZED_VALUE, [start of procedure twoResourcesCommonFix(),exception java.io.FileNotFoundException]

Loading…
Cancel
Save