diff --git a/infer/src/bufferoverrun/bufferOverrunChecker.ml b/infer/src/bufferoverrun/bufferOverrunChecker.ml index 2e718a0e0..72d7c362c 100644 --- a/infer/src/bufferoverrun/bufferOverrunChecker.ml +++ b/infer/src/bufferoverrun/bufferOverrunChecker.ml @@ -157,6 +157,31 @@ module TransferFunctions (CFG : ProcCfg.S) = struct match instr with | Load (id, _, _, _) when Ident.is_none id -> mem + | Load (id, Exp.Lvar pvar, _, location) when Pvar.is_compile_constant pvar -> ( + match Pvar.get_initializer_pname pvar with + | Some callee_pname -> ( + match Ondemand.analyze_proc_name ~caller_pdesc:pdesc callee_pname with + | Some callee_summary -> ( + match Payload.of_summary callee_summary with + | Some payload -> + let callee_mem = BufferOverrunSummary.get_output payload in + let v = Dom.Mem.find (Loc.of_pvar pvar) callee_mem in + Dom.Mem.add_stack (Loc.of_id id) v mem + | None -> + L.(debug BufferOverrun Verbose) + "/!\\ Initializer of global constant %a at %a has no inferbo payload@\n" + (Pvar.pp Pp.text) pvar Location.pp location ; + Dom.Mem.add_unknown_from id ~callee_pname ~location mem ) + | None -> + L.(debug BufferOverrun Verbose) + "/!\\ Unknown initializer of global constant %a at %a@\n" (Pvar.pp Pp.text) pvar + Location.pp location ; + Dom.Mem.add_unknown_from id ~callee_pname ~location mem ) + | None -> + L.(debug BufferOverrun Verbose) + "/!\\ Failed to get initializer name of global constant %a at %a@\n" + (Pvar.pp Pp.text) pvar Location.pp location ; + Dom.Mem.add_unknown id ~location mem ) | Load (id, exp, _, _) -> BoUtils.Exec.load_val id (Sem.eval exp mem) mem | Store (exp1, _, exp2, location) -> @@ -224,7 +249,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct L.(debug BufferOverrun Verbose) "/!\\ Call to non-const function %a at %a" Exp.pp fun_exp Location.pp location in - Dom.Mem.add_unknown_from_funcptr id ~location mem + Dom.Mem.add_unknown id ~location mem | Remove_temps (temps, _) -> Dom.Mem.remove_temps temps mem | Abstract _ | Nullify _ -> diff --git a/infer/src/bufferoverrun/bufferOverrunDomain.ml b/infer/src/bufferoverrun/bufferOverrunDomain.ml index 249d36e56..50e7b615d 100644 --- a/infer/src/bufferoverrun/bufferOverrunDomain.ml +++ b/infer/src/bufferoverrun/bufferOverrunDomain.ml @@ -972,7 +972,7 @@ module Mem = struct f_lift (MemReach.add_unknown_from id ~callee_pname:(Some callee_pname) ~location) - let add_unknown_from_funcptr : Ident.t -> location:Location.t -> t -> t = + let add_unknown : Ident.t -> location:Location.t -> t -> t = fun id ~location -> f_lift (MemReach.add_unknown_from id ~callee_pname:None ~location) diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/class.cpp b/infer/tests/codetoanalyze/cpp/bufferoverrun/class.cpp index c880e1c07..8c42acee8 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/class.cpp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/class.cpp @@ -276,3 +276,17 @@ void return_class_Bad() { my_class4* x = (my_class4*)my_malloc(); x->b[5] = 0; } + +struct S { + static constexpr unsigned int x = 32; +}; + +void use_global_Good() { + int a[50]; + a[S::x] = 0; +} + +void use_global_Bad() { + int a[30]; + a[S::x] = 0; +} diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp index 5065fad18..edc920f22 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp @@ -16,6 +16,7 @@ codetoanalyze/cpp/bufferoverrun/class.cpp, placement_new_Bad, 3, BUFFER_OVERRUN_ codetoanalyze/cpp/bufferoverrun/class.cpp, placement_new_overload1_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Offset: 10 Size: 5] codetoanalyze/cpp/bufferoverrun/class.cpp, placement_new_overload2_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Offset: 10 Size: 5] codetoanalyze/cpp/bufferoverrun/class.cpp, return_class_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Return,ArrayAccess: Offset: 5 Size: 5] +codetoanalyze/cpp/bufferoverrun/class.cpp, use_global_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [ArrayDeclaration,Assignment,ArrayAccess: Offset: 32 Size: 30] codetoanalyze/cpp/bufferoverrun/external.cpp, extern_bad, 5, BUFFER_OVERRUN_U5, no_bucket, ERROR, [Unknown value from: lib,Assignment,ArrayAccess: Offset: [-oo, +oo] Size: [0, +oo]] codetoanalyze/cpp/bufferoverrun/external.cpp, extern_bad, 10, BUFFER_OVERRUN_L1, no_bucket, ERROR, [ArrayDeclaration,ArrayAccess: Offset: 30 Size: 10] codetoanalyze/cpp/bufferoverrun/folly_split.cpp, folly_split::do_not_ignore_empty2_Good, 3, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Call,Binop: (4 * [1, +oo]):unsigned64] @@ -47,8 +48,8 @@ codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM_lI, 2, INTEGER_OVERFLOW_L5, codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM_lI, 2, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Assignment,Return,Assignment,Return,Assignment,Binop: ([-oo, +oo] - 1):signed32] codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM_uI_FP, 0, BUFFER_OVERRUN_S2, no_bucket, ERROR, [Parameter: bi,Call,Call,ArrayDeclaration,Assignment,Parameter: index,ArrayAccess: Offset: [-1+max(1, bi.lb), -1+max(1, bi.ub)] Size: [0, +oo]] codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM_uI_FP, 0, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Binop: (4 * [0, +oo]):unsigned64] -codetoanalyze/cpp/bufferoverrun/repro1.cpp, am_Good, 5, BUFFER_OVERRUN_L5, no_bucket, ERROR, [Call,Call,Call,Assignment,Call,Call,Call,Parameter: bi,Call,Call,ArrayDeclaration,Assignment,Parameter: index,ArrayAccess: Offset: [0, +oo] Size: [0, +oo]] -codetoanalyze/cpp/bufferoverrun/repro1.cpp, am_Good, 5, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Call,Assignment,Call,Call,Call,Parameter: bi,Binop: ([-oo, +oo] - 1):signed32 by call to `ral_FP` ] +codetoanalyze/cpp/bufferoverrun/repro1.cpp, am_Good, 5, BUFFER_OVERRUN_L5, no_bucket, ERROR, [Call,Call,Call,Assignment,Assignment,Call,Call,Call,Parameter: bi,Call,Call,ArrayDeclaration,Assignment,Parameter: index,ArrayAccess: Offset: [0, +oo] Size: [0, +oo]] +codetoanalyze/cpp/bufferoverrun/repro1.cpp, am_Good, 5, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Call,Assignment,Assignment,Call,Call,Call,Parameter: bi,Binop: ([-oo, +oo] - 1):signed32 by call to `ral_FP` ] codetoanalyze/cpp/bufferoverrun/simple_vector.cpp, my_vector_oob_Bad, 2, BUFFER_OVERRUN_L2, no_bucket, ERROR, [Call,Call,ArrayDeclaration,Assignment,Parameter: i,ArrayAccess: Offset: v[*]._size Size: v[*]._size by call to `int_vector_access_at` ] codetoanalyze/cpp/bufferoverrun/std_array.cpp, new_int1_Bad, 3, INFERBO_ALLOC_IS_BIG, no_bucket, ERROR, [Assignment,Alloc: Length: 4611686018427387903] codetoanalyze/cpp/bufferoverrun/std_array.cpp, new_int2_Bad, 3, INFERBO_ALLOC_IS_BIG, no_bucket, ERROR, [Assignment,Alloc: Length: 9223372036854775807]