diff --git a/infer/src/bufferoverrun/bufferOverrunAnalysis.ml b/infer/src/bufferoverrun/bufferOverrunAnalysis.ml index 7a8ba2333..890072216 100644 --- a/infer/src/bufferoverrun/bufferOverrunAnalysis.ml +++ b/infer/src/bufferoverrun/bufferOverrunAnalysis.ml @@ -398,11 +398,14 @@ module TransferFunctions = struct let {BoUtils.ReplaceCallee.pname= callee_pname; params; is_params_ref} = BoUtils.ReplaceCallee.replace_make_shared tenv get_formals callee_pname params in - match (get_summary callee_pname, get_formals callee_pname) with - | Some callee_exit_mem, Some callee_formals -> + match + (callee_pname, Tenv.get_summary_formals tenv ~get_summary ~get_formals callee_pname) + with + | callee_pname, `Found (callee_exit_mem, callee_formals) + | _, `FoundFromSubclass (callee_pname, callee_exit_mem, callee_formals) -> instantiate_mem ~is_params_ref integer_type_widths ret callee_formals callee_pname params mem callee_exit_mem location - | _, _ -> + | _, `NotFound -> (* This may happen for procedures with a biabduction model too. *) L.d_printfln_escaped "/!\\ Unknown call to %a" Procname.pp callee_pname ; Dom.Mem.add_unknown_from ret ~callee_pname ~location mem ) ) diff --git a/infer/tests/codetoanalyze/java/bufferoverrun/InheritanceTest.java b/infer/tests/codetoanalyze/java/bufferoverrun/InheritanceTest.java new file mode 100644 index 000000000..19c01c5d8 --- /dev/null +++ b/infer/tests/codetoanalyze/java/bufferoverrun/InheritanceTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +class InheritanceTest { + interface MyInterface { + public int foo(); + } + + class UniqueImpl implements MyInterface { + public int foo() { + return 5; + } + } + + public void call_interface_method_Good(MyInterface x) { + int a[] = new int[10]; + a[x.foo()] = 0; + } + + public void call_interface_method_Bad(MyInterface x) { + int a[] = new int[5]; + a[x.foo()] = 0; + } + + interface MyInterface2 { + public int foo(); + } + + abstract class AbsImpl implements MyInterface2 { + public abstract int foo(); + } + + class Impl1 extends AbsImpl { + @Override + public int foo() { + return 10; + } + } + + class Impl2 extends AbsImpl { + @Override + public int foo() { + return 5; + } + } + + /* By heuristics, [Impl1.foo] is selected. It is hard to say good or bad. */ + public void call_interface_method2(MyInterface2 x) { + int a[] = new int[10]; + a[x.foo()] = 0; + } +} diff --git a/infer/tests/codetoanalyze/java/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/java/bufferoverrun/issues.exp index 08db779de..0d7b19099 100644 --- a/infer/tests/codetoanalyze/java/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/java/bufferoverrun/issues.exp @@ -28,6 +28,8 @@ codetoanalyze/java/bufferoverrun/ArrayListTest.java, ArrayListTest.remove_in_loo codetoanalyze/java/bufferoverrun/ArrayMember.java, codetoanalyze.java.bufferoverrun.ArrayMember.load_array_member_Bad():void, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Parameter `this.buf[*]`,Assignment,,Array declaration,Array access: Offset: [max(10, this.buf[*].lb), min(10, this.buf[*].ub)] Size: 10] codetoanalyze/java/bufferoverrun/CompressedData.java, codetoanalyze.java.bufferoverrun.CompressedData.decompressData(codetoanalyze.java.bufferoverrun.CompressedData$D):int, 9, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Parameter `this.yy`,,Parameter `d.cci[*].s`,Assignment,Binary operation: ([0, this.yy - 1] × d.cci[*].s):signed32] codetoanalyze/java/bufferoverrun/External.java, External.external_function_Bad(external.library.SomeExternalClass):void, 1, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Assignment,,Assignment,Binary operation: ([-oo, +oo] + [-oo, +oo]):signed32] +codetoanalyze/java/bufferoverrun/InheritanceTest.java, InheritanceTest.call_interface_method2(InheritanceTest$MyInterface2):void, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Assignment,Assignment,,Array declaration,Array access: Offset: 10 Size: 10] +codetoanalyze/java/bufferoverrun/InheritanceTest.java, InheritanceTest.call_interface_method_Bad(InheritanceTest$MyInterface):void, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Assignment,Assignment,,Array declaration,Array access: Offset: 5 Size: 5] codetoanalyze/java/bufferoverrun/StringTest.java, StringTest.constant_Bad():void, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 5 Size: 5] codetoanalyze/java/bufferoverrun/StringTest.java, StringTest.constant_explicit_constructor_Bad():void, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 5 Size: 5] codetoanalyze/java/bufferoverrun/StringTest.java, StringTest.copy_constructor_Bad():void, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 5 Size: 5]