diff --git a/infer/src/checkers/uninit.ml b/infer/src/checkers/uninit.ml index 272b6e103..78dc558f2 100644 --- a/infer/src/checkers/uninit.ml +++ b/infer/src/checkers/uninit.ml @@ -120,6 +120,14 @@ module TransferFunctions (CFG : ProcCfg.S) = struct uninit_vars + let remove_all_array_elements base uninit_vars = + match base with + | _, {Typ.desc= Tptr (elt, _)} -> + D.remove (base, [AccessPath.ArrayAccess (elt, [])]) uninit_vars + | _ -> + uninit_vars + + let remove_init_fields base formal_var uninit_vars init_fields = let subst_formal_actual_fields initialized_fields = D.map @@ -228,8 +236,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct in let prepost = update_prepost lhs_ap rhs_expr in (* check on lhs_typ to avoid false positive when assigning a pointer to another *) - if should_report_var pdesc tenv uninit_vars (rhs_base, al) && not (Typ.is_pointer lhs_typ) - then report_intra (rhs_base, al) loc (snd extras) ; + let is_lhs_not_a_pointer = + match AccessPath.get_typ lhs_ap tenv with + | None -> + false + | Some lhs_ap_typ -> + not (Typ.is_pointer lhs_ap_typ) + in + if should_report_var pdesc tenv uninit_vars (rhs_base, al) && is_lhs_not_a_pointer then + report_intra (rhs_base, al) loc (snd extras) ; {astate with uninit_vars; prepost} | Assign (lhs_access_expr, rhs, _) -> let (lhs_ap, apl) as lhs = AccessExpression.to_access_path lhs_access_expr in @@ -273,8 +288,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct if Config.uninit_interproc then remove_initialized_params pdesc call acc idx (base, al) true else - let acc' = D.remove (base, al) acc in - remove_all_fields tenv base acc' + D.remove (base, al) acc |> remove_all_fields tenv base + |> remove_all_array_elements base | _ -> acc ) | HilExp.Closure (_, apl) -> diff --git a/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp b/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp index 5918f7bba..1f0481f01 100644 --- a/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp +++ b/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp @@ -7,6 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ +#include + void init(int* i) { *i = 10; } void init_bool(bool* i) { *i = false; } @@ -133,6 +135,25 @@ void ok8() { // reference. } +struct A { + int* ptr; +}; + +void ok9() { + int i; + A a; + a.ptr = &i; // no report since the variable could be initialized when passed + // by reference. + init(a.ptr); +} + +int array_initialized_ok(int N, int index) { + int array[N]; + std::fill_n(array, N, 0.0f); + int value = array[index]; + return value; +} + int ret_undef_bad() { int* p; return *p; // report as p was not initialized @@ -147,7 +168,7 @@ int ret_undef_FP() { void use_an_int2(int*); -int ok9() { +int ok10() { int buf[1024]; use_an_int2(buf); // no report as we pass the pointer to buf return 1;