From 1305db390aae1882168439ce1b0151b598edaf12 Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Tue, 14 Jan 2020 02:12:08 -0800 Subject: [PATCH] [infer] Load global array constant Summary: This diff enables loading array contents of global constant. Reviewed By: ezgicicek Differential Revision: D19329014 fbshipit-source-id: 9dfae2754 --- .../bufferoverrun/bufferOverrunAnalysis.ml | 41 ++++++++++++------- .../cpp/bufferoverrun/global.cpp | 19 +++++++++ .../cpp/bufferoverrun/issues.exp | 1 + 3 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp diff --git a/infer/src/bufferoverrun/bufferOverrunAnalysis.ml b/infer/src/bufferoverrun/bufferOverrunAnalysis.ml index 862daa29f..47436c8bd 100644 --- a/infer/src/bufferoverrun/bufferOverrunAnalysis.ml +++ b/infer/src/bufferoverrun/bufferOverrunAnalysis.ml @@ -276,6 +276,23 @@ module TransferFunctions = struct None + let load_global_constant get_summary id pvar location mem ~find_from_initializer = + match Pvar.get_initializer_pname pvar with + | Some callee_pname -> ( + match get_summary callee_pname with + | Some callee_mem -> + let v = find_from_initializer callee_mem in + Dom.Mem.add_stack (Loc.of_id id) v mem + | None -> + L.d_printfln_escaped "/!\\ Unknown initializer of global constant %a" (Pvar.pp Pp.text) + pvar ; + Dom.Mem.add_unknown_from id ~callee_pname ~location mem ) + | None -> + L.d_printfln_escaped "/!\\ Failed to get initializer name of global constant %a" + (Pvar.pp Pp.text) pvar ; + Dom.Mem.add_unknown id ~location mem + + let exec_instr : Dom.Mem.t -> extras ProcData.t -> CFG.Node.t -> Sil.instr -> Dom.Mem.t = fun mem {summary; tenv; extras= {get_summary; get_formals; oenv= {integer_type_widths}}} node instr -> @@ -283,21 +300,15 @@ module TransferFunctions = struct | Load {id} when Ident.is_none id -> mem | Load {id; e= Exp.Lvar pvar; loc= location} - when Pvar.is_compile_constant pvar || Pvar.is_ice pvar -> ( - match Pvar.get_initializer_pname pvar with - | Some callee_pname -> ( - match get_summary callee_pname with - | Some callee_mem -> - let v = Dom.Mem.find (Loc.of_pvar pvar) callee_mem in - Dom.Mem.add_stack (Loc.of_id id) v mem - | None -> - L.d_printfln_escaped "/!\\ Unknown initializer of global constant %a" (Pvar.pp Pp.text) - pvar ; - Dom.Mem.add_unknown_from id ~callee_pname ~location mem ) - | None -> - L.d_printfln_escaped "/!\\ Failed to get initializer name of global constant %a" - (Pvar.pp Pp.text) pvar ; - Dom.Mem.add_unknown id ~location mem ) + when Pvar.is_compile_constant pvar || Pvar.is_ice pvar -> + load_global_constant get_summary id pvar location mem + ~find_from_initializer:(fun callee_mem -> Dom.Mem.find (Loc.of_pvar pvar) callee_mem) + | Load {id; e= Exp.Lindex (Exp.Lvar pvar, _); loc= location} + when Pvar.is_compile_constant pvar || Pvar.is_ice pvar -> + load_global_constant get_summary id pvar location mem + ~find_from_initializer:(fun callee_mem -> + let locs = Dom.Mem.find (Loc.of_pvar pvar) callee_mem |> Dom.Val.get_all_locs in + Dom.Mem.find_set locs callee_mem ) | Load {id; e= exp; typ; loc= location} -> ( let model_env = let pname = Summary.get_proc_name summary in diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp b/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp new file mode 100644 index 000000000..7497cde8b --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/global.cpp @@ -0,0 +1,19 @@ +/* + * 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. + */ +static constexpr int ConstantGlobal[] = {5}; + +void access_constant_global_Bad() { + int a[5]; + a[ConstantGlobal[0]] = 3; +} + +static int StaticGlobal[][3] = { + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; + +void access_static_global1_Bad_FN() { int* p = StaticGlobal[10]; } + +void access_static_global2_Bad_FN() { int a = StaticGlobal[0][10]; } diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp index eb6d710a9..20ca0b8a5 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp @@ -49,6 +49,7 @@ codetoanalyze/cpp/bufferoverrun/folly_split.cpp, folly_split::FP_do_not_ignore_e codetoanalyze/cpp/bufferoverrun/folly_split.cpp, folly_split::do_not_ignore_empty_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Assignment,Array access: Offset: 0 Size: 0] codetoanalyze/cpp/bufferoverrun/function_call.cpp, call_by_ref_bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Assignment,,Array declaration,Array access: Offset: -1 Size: 10] codetoanalyze/cpp/bufferoverrun/function_call.cpp, call_loop_with_init_S_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Call,Parameter `length`,Assignment,,Array declaration,Array access: Offset: 10 Size: 10] +codetoanalyze/cpp/bufferoverrun/global.cpp, access_constant_global_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Array declaration,Array access: Offset: 5 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Array declaration,Assignment,Array access: Offset: 5 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_flexible_array_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 7 Size: 5] codetoanalyze/cpp/bufferoverrun/realloc.cpp, realloc_struct1_Bad, 4, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Assignment,,Array declaration,Assignment,Array access: Offset: 5 Size: 5]