diff --git a/infer/src/bufferoverrun/bufferOverrunDomain.ml b/infer/src/bufferoverrun/bufferOverrunDomain.ml index b9406be04..9a0356e78 100644 --- a/infer/src/bufferoverrun/bufferOverrunDomain.ml +++ b/infer/src/bufferoverrun/bufferOverrunDomain.ml @@ -2020,8 +2020,18 @@ module MemReach = struct let init : get_summary -> OndemandEnv.t -> t = fun get_summary oenv -> let find_global_array loc = - Option.bind (Loc.get_global_array_initializer loc) ~f:(fun pname -> - Option.bind (get_summary pname) ~f:(find_opt loc) ) + let open IOption.Let_syntax in + let* pname = Loc.get_global_array_initializer loc in + let* m = get_summary pname in + match loc with + | BoField.Field {prefix; fn} when Loc.is_global prefix -> + (* This case handles field access of global array: + n$0 = *x[n].field *) + let+ v = find_opt prefix m in + let locs = Val.get_all_locs v |> PowLoc.append_field ~fn in + find_set locs m + | _ -> + find_opt loc m in { stack_locs= StackLocs.bot ; mem_pure= MemPure.bot diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp b/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp index 50a8fbce8..e619ee405 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp @@ -23,3 +23,23 @@ static int StaticGlobal[][3] = { void access_static_global1_Bad() { int* p = StaticGlobal[10]; } void access_static_global2_Bad() { int a = StaticGlobal[0][10]; } + +class Foo { + + public: + int p; + Foo(int x) { p = x; } +}; + +static const Foo ConstantGlobalFoos[] = {{8}}; + +void access_via_class_field_assignment_constant_global_Bad() { + int a[5]; + const Foo foo = ConstantGlobalFoos[0]; + a[foo.p] = 3; +} + +void access_via_class_field_constant_global_Bad() { + int a[5]; + a[ConstantGlobalFoos[0].p] = 3; +} diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp index 8a7207f69..f534f6f7b 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp @@ -53,6 +53,8 @@ codetoanalyze/cpp/bufferoverrun/global.cpp, access_constant_global_Bad, 2, BUFFE codetoanalyze/cpp/bufferoverrun/global.cpp, access_static_global1_Bad, 0, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 10 Size: 5] codetoanalyze/cpp/bufferoverrun/global.cpp, access_static_global2_Bad, 0, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 10 Size: 3] codetoanalyze/cpp/bufferoverrun/global.cpp, access_via_assignment_constant_global_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Array declaration,Array access: Offset: 5 Size: 5] +codetoanalyze/cpp/bufferoverrun/global.cpp, access_via_class_field_assignment_constant_global_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Parameter `x`,Assignment,Call,Parameter `__param_0->p`,Assignment,,Array declaration,Array access: Offset: 8 Size: 5] +codetoanalyze/cpp/bufferoverrun/global.cpp, access_via_class_field_constant_global_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Parameter `x`,Assignment,,Array declaration,Array access: Offset: 8 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Set array size,Assignment,Array access: Offset: 5 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_flexible_array_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Set array size,Array access: Offset: 7 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_struct1_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Set array size,Assignment,Array access: Offset: 5 Size: 5] diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index 29b958fcb..1da146908 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -233,8 +233,8 @@ codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.setMObjects:, 3 codetoanalyze/objc/performance/mutable_copy_test.m, loop_over_mutable_copy_linear, 31 + 3 ⋅ b->_mObjects->elements.length.ub + 3 ⋅ (b->_mObjects->elements.length.ub + 1), OnUIThread:false, [{b->_mObjects->elements.length.ub + 1},Loop,{b->_mObjects->elements.length.ub},Loop] codetoanalyze/objc/performance/purity.m, loop, 6006 + 1000 ⋅ |fun_ptr|, OnUIThread:false, [] codetoanalyze/objc/performance/struct_test.m, __infer_globals_initializer_mSpecs, 4, OnUIThread:false, [] -codetoanalyze/objc/performance/struct_test.m, const_struct_field_read_constant_FP, 4 + mSpecs.fileName->strlen.ub, OnUIThread:false, [{mSpecs.fileName->strlen.ub},Modeled call to NSString.stringWithUTF8String:] -codetoanalyze/objc/performance/struct_test.m, loop_array_struct_constant, 9, OnUIThread:false, [] +codetoanalyze/objc/performance/struct_test.m, const_struct_field_read_constant, 9, OnUIThread:false, [] +codetoanalyze/objc/performance/struct_test.m, loop_array_struct_constant, 17, OnUIThread:false, [] codetoanalyze/objc/performance/switch_continue.m, test_switch_FN, 600, OnUIThread:false, [] codetoanalyze/objc/performance/switch_continue.m, unroll_loop, 15 + (n - 1) + 11 ⋅ (max(1, n)), OnUIThread:false, [{max(1, n)},Loop,{n - 1},Loop] codetoanalyze/objc/performance/two_loops_symbolic.m, nop, 1, OnUIThread:false, [] diff --git a/infer/tests/codetoanalyze/objc/performance/struct_test.m b/infer/tests/codetoanalyze/objc/performance/struct_test.m index 1374e3f06..bf53bf8c6 100644 --- a/infer/tests/codetoanalyze/objc/performance/struct_test.m +++ b/infer/tests/codetoanalyze/objc/performance/struct_test.m @@ -19,7 +19,7 @@ static const MSpec mSpecs[] = { {SPEC_FILE_NAME("io")}, }; -void const_struct_field_read_constant_FP() { +void const_struct_field_read_constant() { MSpec spec = mSpecs[0]; NSString* fileName = @(spec.fileName); // filename is constant, so this should be O(1) @@ -28,5 +28,6 @@ void const_struct_field_read_constant_FP() { void loop_array_struct_constant() { const MSpec* const endSpec = ((const MSpec*)mSpecs) + ARRAY_COUNT(mSpecs); for (const MSpec* spec = (const MSpec*)mSpecs; spec < endSpec; spec++) { + NSString* fileName = @(spec->fileName); } }