From 3a40afcd224e7714d22ee49c51e2193a5f155062 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Tue, 13 Mar 2018 19:39:35 -0700 Subject: [PATCH] [ownership] directly assigning any field of an aggregate struct counts as initialization Summary: Aggregate initialization (e.g., `S s{1, 2}`) doesn't invoke a contructor. Our frontend translates aggregation initialization as assigning to each field in the struct. To avoid the appearance of the struct being uninitialized, count any assignment to a field of an aggregate struct as initializing the struct. Reviewed By: jeremydubreil Differential Revision: D7189671 fbshipit-source-id: ace02fc --- infer/src/checkers/Ownership.ml | 13 ++++++++++ .../codetoanalyze/cpp/ownership/basics.cpp | 25 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 infer/tests/codetoanalyze/cpp/ownership/basics.cpp diff --git a/infer/src/checkers/Ownership.ml b/infer/src/checkers/Ownership.ml index 64595067d..b4077f256 100644 --- a/infer/src/checkers/Ownership.ml +++ b/infer/src/checkers/Ownership.ml @@ -217,11 +217,24 @@ module TransferFunctions (CFG : ProcCfg.S) = struct false + let is_aggregate (_, typ) = + match typ.Typ.desc with + | Tstruct _ -> + (* TODO: we could compute this precisely by recursively checking all of the fields of the + type, but that's going to be expensive. will add it to the frontend instead *) + true + | _ -> + false + + let exec_instr (astate: Domain.astate) (proc_data: extras ProcData.t) _ (instr: HilInstr.t) = let summary = proc_data.extras in match instr with | Assign (Base lhs_base, rhs_exp, loc) -> Domain.handle_var_assign lhs_base rhs_exp loc summary astate + | Assign (FieldOffset (Base lhs_base, _), rhs_exp, loc) when is_aggregate lhs_base -> + (* assume assigning to any field of an aggregate struct re-initalizes the struct *) + Domain.handle_var_assign lhs_base rhs_exp loc summary astate | Assign (lhs_access_exp, rhs_exp, loc) -> (* assign to field, array, indirectly with &/*, or a combination *) Domain.exp_add_reads rhs_exp loc summary astate diff --git a/infer/tests/codetoanalyze/cpp/ownership/basics.cpp b/infer/tests/codetoanalyze/cpp/ownership/basics.cpp new file mode 100644 index 000000000..70f471d1f --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/ownership/basics.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +struct Aggregate { + int i; + + ~Aggregate() {} +}; + +void aggregate_reassign_ok() { + const int len = 5; + Aggregate arr[len]; + for (int i = 0; i < len; i++) { + Aggregate s = {1}; + // assign with curly bracket syntax doesn't call constructor; need to + // recognize that this is a reassignment anyway + arr[0] = s; // shouldn't be flagged as a use-after-lifetime + } +}