From ca04002f6c6e7e56b3d22995859eefdd02150beb Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Tue, 11 Feb 2020 03:06:33 -0800 Subject: [PATCH] [inferbo] Revise finding constructors on std::make_shared Summary: When finding a proper constructor for `std::make_shared`, the given parameter types are sometimes slightly different, e.g., const int vs int. This diff loosens the condition of the types on finding constructors. Reviewed By: ngorogiannis Differential Revision: D19743198 fbshipit-source-id: f90213109 --- infer/src/IR/Typ.ml | 10 +++++-- infer/src/IR/Typ.mli | 4 +-- infer/src/bufferoverrun/bufferOverrunUtils.ml | 5 ++-- .../cpp/bufferoverrun/issues.exp | 2 ++ .../cpp/bufferoverrun/smart_ptr.cpp | 28 +++++++++++++++++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index b7a3ef469..341395af6 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -220,10 +220,14 @@ module T = struct equal_ikind ikind1 ikind2 | Tfloat fkind1, Tfloat fkind2 -> equal_fkind fkind1 fkind2 - | Tvoid, Tvoid -> + | Tvoid, Tvoid | Tfun, Tfun -> true | Tptr (t1, ptr_kind1), Tptr (t2, ptr_kind2) -> equal_ptr_kind ptr_kind1 ptr_kind2 && equal_ignore_quals t1 t2 + | Tstruct name1, Tstruct name2 -> + equal_name name1 name2 + | TVar s1, TVar s2 -> + String.equal s1 s2 | Tarray {elt= t1}, Tarray {elt= t2} -> equal_ignore_quals t1 t2 | _, _ -> @@ -573,7 +577,9 @@ let unsome s = function (** turn a *T into a T. fails if [typ] is not a pointer type *) let strip_ptr typ = match typ.desc with Tptr (t, _) -> t | _ -> assert false -let is_ptr_to t ~ptr = match ptr.desc with Tptr (t', _) -> equal t t' | _ -> false +let is_ptr_to_ignore_quals t ~ptr = + match ptr.desc with Tptr (t', _) -> equal_ignore_quals t t' | _ -> false + (** If an array type, return the type of the element. If not, return the default type if given, otherwise raise an exception *) diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index eeee8225f..7f7af17a3 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -318,8 +318,8 @@ val name : t -> Name.t option val strip_ptr : t -> t (** turn a *T into a T. fails if [t] is not a pointer type *) -val is_ptr_to : t -> ptr:t -> bool -(** check if [ptr] is a pointer type to [t] *) +val is_ptr_to_ignore_quals : t -> ptr:t -> bool +(** check if [ptr] is a pointer type to [t], ignoring quals *) val array_elem : t option -> t -> t (** If an array type, return the type of the element. diff --git a/infer/src/bufferoverrun/bufferOverrunUtils.ml b/infer/src/bufferoverrun/bufferOverrunUtils.ml index d64ca8302..c9bb5e451 100644 --- a/infer/src/bufferoverrun/bufferOverrunUtils.ml +++ b/infer/src/bufferoverrun/bufferOverrunUtils.ml @@ -345,11 +345,12 @@ module ReplaceCallee = struct when Int.equal (List.length parameters) num_params -> ( match get_formals pname |> Option.map ~f:(List.map ~f:snd) with | Some (this_typ :: formal_typs) -> ( - Typ.is_ptr_to class_typ ~ptr:this_typ + Typ.is_ptr_to_ignore_quals class_typ ~ptr:this_typ && match List.for_all2 param_ref_typs formal_typs ~f:(fun param_ref_typ formal_typ -> - Typ.is_ptr_to formal_typ ~ptr:param_ref_typ ) + Typ.equal_ignore_quals formal_typ param_ref_typ + || Typ.is_ptr_to_ignore_quals formal_typ ~ptr:param_ref_typ ) with | List.Or_unequal_lengths.Ok b -> b diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp index 1e7156dba..d98b0f3e4 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/issues.exp @@ -72,6 +72,8 @@ codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM::lI_FP, 2, INTEGER_OVERFLOW_ codetoanalyze/cpp/bufferoverrun/repro1.cpp, LM::uI, 0, BUFFER_OVERRUN_U5, no_bucket, ERROR, [,Unknown value from: std::unique_ptr,std::default_delete>>::operator->,Array access: Offset: [-oo, +oo] Size: [0, +oo]] codetoanalyze/cpp/bufferoverrun/repro1.cpp, am_Good_FP, 5, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [Call,Call,Call,Assignment,Assignment,Call,Parameter `t->bI`,Call,Assignment,Call,,Parameter `bi`,Binary operation: ([-oo, +oo] - 1):signed32 by call to `ral_good` ] codetoanalyze/cpp/bufferoverrun/simple_vector.cpp, my_vector_oob_Bad, 2, BUFFER_OVERRUN_L2, no_bucket, ERROR, [Parameter `v->_size`,Call,,Parameter `i`,,Parameter `this->_size`,Array declaration,Assignment,Array access: Offset: v->_size Size: v->_size by call to `int_vector::access_at` ] +codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp, smart_ptr::shared_ptr_with_const_int_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Assignment,Call,,Parameter `i`,,Array declaration,Array access: Offset: 8 Size: 5 by call to `smart_ptr::my_class::my_class` ] +codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp, smart_ptr::shared_ptr_with_std_string_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Assignment,Call,,Parameter `i`,,Array declaration,Array access: Offset: 8 Size: 5 by call to `smart_ptr::my_class::my_class` ] codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp, smart_ptr::use_shared_ptr1_Bad, 2, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Assignment,Call,,Parameter `i`,,Array declaration,Array access: Offset: 8 Size: 5 by call to `smart_ptr::my_class::my_class` ] codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp, smart_ptr::use_shared_ptr2_Bad, 3, BUFFER_OVERRUN_L1, no_bucket, ERROR, [Assignment,Call,,Parameter `j`,,Array declaration,Array access: Offset: 16 Size: 10 by call to `smart_ptr::my_class::my_class` ] codetoanalyze/cpp/bufferoverrun/std_array.cpp, array_iter1_Bad, 5, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Array access: Offset: 10 Size: 5] diff --git a/infer/tests/codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp b/infer/tests/codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp index a90159a1b..827d7dd1b 100644 --- a/infer/tests/codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp +++ b/infer/tests/codetoanalyze/cpp/bufferoverrun/smart_ptr.cpp @@ -6,6 +6,7 @@ */ #include +#include class smart_ptr { public: @@ -20,6 +21,11 @@ class smart_ptr { int a[10]; a[i + j] = 0; } + + my_class(const std::string& str, int i) { + int a[5]; + a[i] = 0; + } }; void use_shared_ptr1_Good() { @@ -43,4 +49,26 @@ class smart_ptr { int j = 8; std::shared_ptr p = std::make_shared(i, j); } + + void shared_ptr_with_std_string_Good() { + std::string str = "abc"; + int i = 3; + std::shared_ptr p = std::make_shared(str, i); + } + + void shared_ptr_with_std_string_Bad() { + std::string str = "abc"; + int i = 8; + std::shared_ptr p = std::make_shared(str, i); + } + + void shared_ptr_with_const_int_Good() { + const int i = 3; + std::shared_ptr p = std::make_shared(i); + } + + void shared_ptr_with_const_int_Bad() { + const int i = 8; + std::shared_ptr p = std::make_shared(i); + } };