From ada032ee2cb5aa24feb634dfea832b77f184be95 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Thu, 11 Apr 2019 03:55:27 -0700 Subject: [PATCH] [pulse] improve error messages and traces Summary: The previous message formatting had regressed and produced non-sensical messages. More importantly, remove template parameters from error messages to trigger the heuristic in `InferPrint` that deduplicates errors that are on the same line with the same error type and message. Without this we get hundreds of reports that correspond to as many instantiations of the same code. Reviewed By: ngorogiannis Differential Revision: D14747979 fbshipit-source-id: 3c4aad2b1 --- infer/src/IR/Typ.ml | 2 + infer/src/IR/Typ.mli | 3 + infer/src/pulse/PulseDiagnostic.ml | 40 +++++++--- infer/src/pulse/PulseInvalidation.ml | 20 ++++- infer/src/pulse/PulseInvalidation.mli | 2 + infer/src/pulse/PulseTrace.ml | 47 +++++------ infer/src/pulse/PulseTrace.mli | 16 +++- .../codetoanalyze/cpp/pulse/deduplication.cpp | 46 +++++++++++ .../cpp/pulse/interprocedural.cpp | 7 ++ .../tests/codetoanalyze/cpp/pulse/issues.exp | 79 ++++++++++--------- 10 files changed, 184 insertions(+), 78 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/pulse/deduplication.cpp diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index d0e6e3d0c..fda61124c 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -1276,6 +1276,8 @@ module Procname = struct (** Pretty print a proc name *) let pp f pn = F.pp_print_string f (to_string pn) + let describe f pn = F.pp_print_string f (hashable_name pn) + (** hash function for procname *) let hash_pname = Hashtbl.hash diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index d435e367a..f0b084604 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -583,6 +583,9 @@ being the name of the struct, [None] means the parameter is of some other type. val pp : Format.formatter -> t -> unit (** Pretty print a proc name. *) + val describe : Format.formatter -> t -> unit + (** to use in user messages *) + val replace_class : t -> Name.t -> t (** Replace the class name component of a procedure name. In case of Java, replace package and class name. *) diff --git a/infer/src/pulse/PulseDiagnostic.ml b/infer/src/pulse/PulseDiagnostic.ml index a1a86bb63..d056bed01 100644 --- a/infer/src/pulse/PulseDiagnostic.ml +++ b/infer/src/pulse/PulseDiagnostic.ml @@ -15,9 +15,9 @@ type t = ; trace: PulseTrace.t } | StackVariableAddressEscape of {variable: Var.t; location: Location.t} -let pp_access = PulseTrace.pp_action HilExp.AccessExpression.pp +let describe_access = PulseTrace.pp_action HilExp.AccessExpression.pp -let pp_invalidation = PulseTrace.pp_action PulseInvalidation.pp +let describe_invalidation = PulseTrace.pp_action PulseInvalidation.describe let get_location = function | AccessToInvalidAddress {accessed_by} -> @@ -27,9 +27,9 @@ let get_location = function let get_message = function - | AccessToInvalidAddress {accessed_by; invalidated_by; trace} -> - F.asprintf "%a accesses address %a%a past its lifetime" pp_access accessed_by - PulseTrace.pp_interesting_events trace pp_invalidation invalidated_by + | AccessToInvalidAddress {accessed_by; invalidated_by; _} -> + F.asprintf "%a accesses address invalidated by %a past its lifetime" describe_access + accessed_by describe_invalidation invalidated_by | StackVariableAddressEscape {variable} -> let pp_var f var = if Var.is_cpp_temporary var then F.pp_print_string f "C++ temporary" @@ -38,13 +38,33 @@ let get_message = function F.asprintf "address of %a is returned by the function" pp_var variable +let add_errlog_header ~title location errlog = + let depth = 0 in + let tags = [] in + Errlog.make_trace_element depth location title tags :: errlog + + let get_trace = function | AccessToInvalidAddress {accessed_by; invalidated_by; trace} -> - PulseTrace.make_errlog_trace ~depth:0 trace - @ PulseTrace.trace_of_action ~action_name:"invalidated" PulseInvalidation.pp invalidated_by - @ PulseTrace.trace_of_action ~action_name:"accessed" - (Pp.in_backticks HilExp.AccessExpression.pp) - accessed_by + let add_header_if_some ~title location_opt errlog = + match location_opt with + | None -> + errlog + | Some location -> + add_errlog_header ~title location errlog + in + add_errlog_header ~title:"start of end of lifetime trace" + (PulseTrace.location_of_action_start invalidated_by) + @@ PulseTrace.add_errlog_of_action ~nesting:1 ~action_name:"invalidated by" + PulseInvalidation.describe invalidated_by + @@ add_errlog_header ~title:"start of use after lifetime trace" + (PulseTrace.location_of_action_start accessed_by) + @@ PulseTrace.add_errlog_of_action ~nesting:1 ~action_name:"accessed" + (Pp.in_backticks HilExp.AccessExpression.pp) + accessed_by + @@ add_header_if_some ~title:"start of value trace" (PulseTrace.get_start_location trace) + @@ PulseTrace.add_errlog_of_trace ~nesting:1 trace + @@ [] | StackVariableAddressEscape _ -> [] diff --git a/infer/src/pulse/PulseInvalidation.ml b/infer/src/pulse/PulseInvalidation.ml index d55518678..5b3ed72ad 100644 --- a/infer/src/pulse/PulseInvalidation.ml +++ b/infer/src/pulse/PulseInvalidation.ml @@ -58,11 +58,11 @@ let issue_type_of_cause = function IssueType.vector_invalidation -let pp f = function +let describe f = function | CFree access_expr -> - F.fprintf f "by call to `free()` on `%a`" HilExp.AccessExpression.pp access_expr + F.fprintf f "call to `free()` on `%a`" HilExp.AccessExpression.pp access_expr | CppDelete access_expr -> - F.fprintf f "by `delete` on `%a`" HilExp.AccessExpression.pp access_expr + F.fprintf f "`delete` on `%a`" HilExp.AccessExpression.pp access_expr | GoneOutOfScope access_expr -> F.fprintf f "`%a` gone out of scope" HilExp.AccessExpression.pp access_expr | Nullptr -> @@ -70,3 +70,17 @@ let pp f = function | StdVector (std_vector_f, access_expr) -> F.fprintf f "potentially invalidated by call to `%a()` on `%a`" pp_std_vector_function std_vector_f HilExp.AccessExpression.pp access_expr + + +let pp f invalidation = + match invalidation with + | CFree _ -> + F.fprintf f "CFree(%a)" describe invalidation + | CppDelete _ -> + F.fprintf f "CppDelete(%a)" describe invalidation + | GoneOutOfScope _ -> + describe f invalidation + | Nullptr -> + describe f invalidation + | StdVector _ -> + F.fprintf f "StdVector(%a)" describe invalidation diff --git a/infer/src/pulse/PulseInvalidation.mli b/infer/src/pulse/PulseInvalidation.mli index 86e09732b..0add4660f 100644 --- a/infer/src/pulse/PulseInvalidation.mli +++ b/infer/src/pulse/PulseInvalidation.mli @@ -29,4 +29,6 @@ type t = val issue_type_of_cause : t -> IssueType.t +val describe : Format.formatter -> t -> unit + val pp : Format.formatter -> t -> unit diff --git a/infer/src/pulse/PulseTrace.ml b/infer/src/pulse/PulseTrace.ml index bfae11522..a297a29d9 100644 --- a/infer/src/pulse/PulseTrace.ml +++ b/infer/src/pulse/PulseTrace.ml @@ -48,28 +48,22 @@ let pp_breadcrumb fmt crumb = (location_of_breadcrumb crumb) -let errlog_trace_elem_of_breadcrumb ~depth crumb = +let errlog_trace_elem_of_breadcrumb ~nesting crumb = let location = location_of_breadcrumb crumb in let description = F.asprintf "%a" pp_breadcrumb_no_location crumb in let tags = [] in - Errlog.make_trace_element depth location description tags + Errlog.make_trace_element nesting location description tags type t = breadcrumb list [@@deriving compare] let pp f trace = Pp.seq ~print_env:Pp.text_break pp_breadcrumb f trace -let make_errlog_trace ~depth trace = List.rev_map ~f:(errlog_trace_elem_of_breadcrumb ~depth) trace +let add_errlog_of_trace ~nesting trace errlog = + List.rev_map_append ~f:(errlog_trace_elem_of_breadcrumb ~nesting) trace errlog -let pp_last_event f = function - | [] -> - () - | crumb :: _ -> - pp_breadcrumb f crumb ; - (* HACK: needed by the call site *) F.pp_print_string f " " - -let pp_interesting_events f trace = pp_last_event f trace +let get_start_location = function [] -> None | crumb :: _ -> Some (location_of_breadcrumb crumb) type 'a action = | Immediate of {imm: 'a; location: Location.t} @@ -78,9 +72,14 @@ type 'a action = let pp_action pp_immediate fmt = function | Immediate {imm; _} -> - F.fprintf fmt "%a" pp_immediate imm + pp_immediate fmt imm | ViaCall {proc_name; _} -> - F.fprintf fmt "call to `%a`" Typ.Procname.pp proc_name + F.fprintf fmt "call to `%a`" Typ.Procname.describe proc_name + + +let location_of_action_start = function + | Immediate {location; _} | ViaCall {location; _} -> + location let rec immediate_of_action = function @@ -90,24 +89,26 @@ let rec immediate_of_action = function immediate_of_action action -let trace_of_action ~action_name pp_immediate action = - let rec aux ~nesting rev_trace action = +let add_errlog_of_action ~nesting ~action_name pp_immediate action errlog = + let rec aux ~nesting rev_errlog action = match action with | Immediate {imm; location} -> - Errlog.make_trace_element nesting location - (F.asprintf "%s %a here" action_name pp_immediate imm) - [] - :: rev_trace - |> List.rev + let rev_errlog = + Errlog.make_trace_element nesting location + (F.asprintf "%s %a here" action_name pp_immediate imm) + [] + :: rev_errlog + in + List.rev_append rev_errlog errlog | ViaCall {action; proc_name; location} -> aux ~nesting:(nesting + 1) ( Errlog.make_trace_element nesting location - (F.asprintf "%s during call to `%a` here" action_name Typ.Procname.pp proc_name) + (F.asprintf "%s during call to `%a` here" action_name Typ.Procname.describe proc_name) [] - :: rev_trace ) + :: rev_errlog ) action in - aux ~nesting:0 [] action + aux ~nesting [] action let outer_location_of_action = function Immediate {location} | ViaCall {location} -> location diff --git a/infer/src/pulse/PulseTrace.mli b/infer/src/pulse/PulseTrace.mli index 2378ad57c..3a2f673a2 100644 --- a/infer/src/pulse/PulseTrace.mli +++ b/infer/src/pulse/PulseTrace.mli @@ -24,9 +24,10 @@ type t = breadcrumb list [@@deriving compare] val pp : F.formatter -> t -> unit -val make_errlog_trace : depth:int -> t -> Errlog.loc_trace +val add_errlog_of_trace : + nesting:int -> t -> Errlog.loc_trace_elem list -> Errlog.loc_trace_elem list -val pp_interesting_events : F.formatter -> t -> unit +val get_start_location : t -> Location.t option type 'a action = | Immediate of {imm: 'a; location: Location.t} @@ -35,9 +36,16 @@ type 'a action = val pp_action : (F.formatter -> 'a -> unit) -> F.formatter -> 'a action -> unit +val location_of_action_start : 'a action -> Location.t + val immediate_of_action : 'a action -> 'a val outer_location_of_action : 'a action -> Location.t -val trace_of_action : - action_name:string -> (F.formatter -> 'a -> unit) -> 'a action -> Errlog.loc_trace_elem sexp_list +val add_errlog_of_action : + nesting:int + -> action_name:string + -> (F.formatter -> 'a -> unit) + -> 'a action + -> Errlog.loc_trace_elem sexp_list + -> Errlog.loc_trace_elem sexp_list diff --git a/infer/tests/codetoanalyze/cpp/pulse/deduplication.cpp b/infer/tests/codetoanalyze/cpp/pulse/deduplication.cpp new file mode 100644 index 000000000..965307e08 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/deduplication.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +namespace deduplication { + +struct A { + int f; +}; + +template +struct SomeTemplatedClass { + void templated_wrapper_delete_ok(A* a); + void templated_wrapper_access_ok(A* a); + void lifetime_error_bad(A* a); +}; + +template +void SomeTemplatedClass::templated_wrapper_delete_ok(A* a) { + delete a; +} + +template +void SomeTemplatedClass::templated_wrapper_access_ok(A* a) { + int x = a->f; +} + +template +void SomeTemplatedClass::lifetime_error_bad(A* a) { + SomeTemplatedClass::templated_wrapper_delete_ok(a); + SomeTemplatedClass::templated_wrapper_access_ok(a); +} + +void materialize_template_instances() { + A* a1 = new A(); + SomeTemplatedClass x1; + x1.lifetime_error_bad(a1); + + A* a2 = new A(); + SomeTemplatedClass x2; + x2.lifetime_error_bad(a2); +} + +} // namespace deduplication diff --git a/infer/tests/codetoanalyze/cpp/pulse/interprocedural.cpp b/infer/tests/codetoanalyze/cpp/pulse/interprocedural.cpp index ada9ebff2..7cb8be308 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/interprocedural.cpp +++ b/infer/tests/codetoanalyze/cpp/pulse/interprocedural.cpp @@ -38,6 +38,13 @@ void delete_then_read_bad(struct X& x) { wraps_read(x); } +void delete_aliased_then_read_bad(struct X& x) { + struct X* y = &x; + struct X& z = x; + delete y; + wraps_read(z); +} + void delete_then_write_bad(struct X& x) { wraps_delete(&x); wraps_read(x); diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index 6726ed708..1fce70b0a 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp @@ -1,42 +1,45 @@ -codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_branch_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [invalidated by `delete` on `ptr` here,accessed `*(ptr)` here] -codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidated by `delete` on `ptr` here,accessed `ptr` here] -codetoanalyze/cpp/pulse/closures.cpp, implicit_ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [`&(s)` captured as `s`,invalidated `s` gone out of scope here,accessed `&(f)` here] -codetoanalyze/cpp/pulse/closures.cpp, ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [`&(s)` captured as `s`,invalidated `s` gone out of scope here,accessed `&(f)` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_inner_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidated during call to `wraps_delete_inner` here,invalidated by `delete` on `x` here,accessed during call to `wraps_read` here,accessed during call to `wraps_read_inner` here,accessed `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_read_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidated by `delete` on `x` here,accessed during call to `wraps_read` here,accessed during call to `wraps_read_inner` here,accessed `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidated during call to `wraps_delete` here,invalidated during call to `wraps_delete_inner` here,invalidated by `delete` on `x` here,accessed during call to `wraps_read` here,accessed during call to `wraps_read_inner` here,accessed `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, feed_invalid_into_access_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `y`,assigned to `return`,returned from call to `may_return_invalid_ptr_ok()`,assigned to `y`,invalidated during call to `may_return_invalid_ptr_ok` here,invalidated by `delete` on `y` here,accessed during call to `call_store` here,accessed during call to `store` here,accessed `y->p` here] -codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_bad, 12, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `result`,invalidated by `delete` on `result` here,accessed `*(result)` here] +codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_branch_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `ptr` here,start of use after lifetime trace,accessed `*(ptr)` here] +codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `ptr` here,start of use after lifetime trace,accessed `ptr` here] +codetoanalyze/cpp/pulse/closures.cpp, implicit_ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `s` gone out of scope here,start of use after lifetime trace,accessed `&(f)` here,start of value trace,`&(s)` captured as `s`] +codetoanalyze/cpp/pulse/closures.cpp, ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `s` gone out of scope here,start of use after lifetime trace,accessed `&(f)` here,start of value trace,`&(s)` captured as `s`] +codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `templated_wrapper_delete_ok` here,invalidated by `delete` on `a` here,start of use after lifetime trace,accessed during call to `templated_wrapper_access_ok` here,accessed `a->f` here] +codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `templated_wrapper_delete_ok` here,invalidated by `delete` on `a` here,start of use after lifetime trace,accessed during call to `templated_wrapper_access_ok` here,accessed `a->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_aliased_then_read_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `y` here,start of use after lifetime trace,accessed during call to `wraps_read()` here,accessed during call to `wraps_read_inner()` here,accessed `x->f` here,start of value trace,assigned to `z`] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_inner_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `wraps_delete_inner()` here,invalidated by `delete` on `x` here,start of use after lifetime trace,accessed during call to `wraps_read()` here,accessed during call to `wraps_read_inner()` here,accessed `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_read_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `x` here,start of use after lifetime trace,accessed during call to `wraps_read()` here,accessed during call to `wraps_read_inner()` here,accessed `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `wraps_delete()` here,invalidated by during call to `wraps_delete_inner()` here,invalidated by `delete` on `x` here,start of use after lifetime trace,accessed during call to `wraps_read()` here,accessed during call to `wraps_read_inner()` here,accessed `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, feed_invalid_into_access_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `may_return_invalid_ptr_ok()` here,invalidated by `delete` on `y` here,start of use after lifetime trace,accessed during call to `call_store()` here,accessed during call to `store()` here,accessed `y->p` here,start of value trace,assigned to `y`,assigned to `return`,returned from call to `may_return_invalid_ptr_ok()`,assigned to `y`] +codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_bad, 12, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `result` here,start of use after lifetime trace,accessed `*(result)` here,start of value trace,assigned to `result`] codetoanalyze/cpp/pulse/returns.cpp, returns::return_literal_stack_reference_bad, 0, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [] codetoanalyze/cpp/pulse/returns.cpp, returns::return_stack_pointer_bad, 1, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference1_bad, 1, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference2_bad, 1, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [] -codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed `s->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed `s` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed during call to `Simple::Simple` here,accessed `__param_0->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, double_delete_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed `s` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, reassign_field_of_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed `s->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_branch_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed during call to `Simple::Simple` here,accessed `__param_0->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_loop_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `s` here,accessed `s->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::FP_destruct_pointer_contents_then_placement_new2_ok, 2, USE_AFTER_DELETE, no_bucket, ERROR, [returned from call to `(sizeof(use_after_destructor::S),&(s->f))`,invalidated during call to `use_after_destructor::S::~S` here,invalidated during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,accessed during call to `use_after_destructor::S::S` here,accessed `*(this->f)` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::double_destructor_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [variable declared,invalidated during call to `use_after_destructor::S::~S` here,invalidated during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,accessed during call to `use_after_destructor::S::~S` here,accessed during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,accessed `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing1_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,invalidated by `delete` on `alias` here,accessed `s->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`,invalidated by `delete` on `s` here,accessed `alias->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing3_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `s`,assigned to `alias`,invalidated by `delete` on `s` here,accessed `alias->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::reinit_after_explicit_destructor2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [variable declared,invalidated during call to `use_after_destructor::S::~S` here,invalidated during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,accessed during call to `use_after_destructor::S::~S` here,accessed during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,accessed `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_destructor_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [assigned to `this->f`,returned from call to `use_after_destructor::S::S()`,invalidated during call to `use_after_destructor::S::~S` here,invalidated during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,accessed `*(s.f)` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope1_bad, 7, USE_AFTER_DELETE, no_bucket, ERROR, [variable declared,invalidated during call to `use_after_destructor::S::~S` here,invalidated during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,accessed during call to `use_after_destructor::S::~S` here,accessed during call to `use_after_destructor::S::__infer_inner_destructor_~S` here,accessed `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope4_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [variable declared,assigned to `pc`,invalidated `&(c)` gone out of scope here,accessed `pc->f` here] -codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidated by call to `free()` on `x` here,accessed `x` here] -codetoanalyze/cpp/pulse/use_after_free.cpp, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidated by call to `free()` on `x` here,accessed `*(x)` here] -codetoanalyze/cpp/pulse/vector.cpp, FP_init_fill_then_push_back_loop_ok, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, assign_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::assign()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, clear_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::clear()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, deref_local_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, deref_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,assigned to `y`,invalidated potentially invalidated by call to `std::vector::push_back()` on `vec` here,accessed `*(y)` here] -codetoanalyze/cpp/pulse/vector.cpp, emplace_back_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::emplace_back()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::emplace()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, insert_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::insert()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, push_back_loop_bad, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, reserve_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::reserve()` on `vec` here,accessed `*(elt)` here] -codetoanalyze/cpp/pulse/vector.cpp, shrink_to_fit_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalidated potentially invalidated by call to `std::vector::shrink_to_fit()` on `vec` here,accessed `*(elt)` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `s->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `s` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed during call to `Simple` here,accessed `__param_0->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, double_delete_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `s` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, reassign_field_of_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `s->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_branch_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed during call to `Simple` here,accessed `__param_0->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_loop_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `s->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::FP_destruct_pointer_contents_then_placement_new2_ok, 2, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `~S` here,invalidated by during call to `__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,start of use after lifetime trace,accessed during call to `S` here,accessed `*(this->f)` here,start of value trace,returned from call to `(sizeof(use_after_destructor::S),&(s->f))`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::double_destructor_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `~S` here,invalidated by during call to `__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,start of use after lifetime trace,accessed during call to `~S` here,accessed during call to `__infer_inner_destructor_~S` here,accessed `this->f` here,start of value trace,variable declared] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing1_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `alias` here,start of use after lifetime trace,accessed `s->f` here,start of value trace,assigned to `s`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `alias->f` here,start of value trace,assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing3_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `delete` on `s` here,start of use after lifetime trace,accessed `alias->f` here,start of value trace,assigned to `s`,assigned to `alias`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::reinit_after_explicit_destructor2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `~S` here,invalidated by during call to `__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,start of use after lifetime trace,accessed during call to `~S` here,accessed during call to `__infer_inner_destructor_~S` here,accessed `this->f` here,start of value trace,variable declared] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_destructor_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `~S` here,invalidated by during call to `__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,start of use after lifetime trace,accessed `*(s.f)` here,start of value trace,assigned to `this->f`,returned from call to `use_after_destructor::S::S()`] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope1_bad, 7, USE_AFTER_DELETE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by during call to `~S` here,invalidated by during call to `__infer_inner_destructor_~S` here,invalidated by `delete` on `this->f` here,start of use after lifetime trace,accessed during call to `~S` here,accessed during call to `__infer_inner_destructor_~S` here,accessed `this->f` here,start of value trace,variable declared] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope4_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [start of end of lifetime trace,invalidated by `&(c)` gone out of scope here,start of use after lifetime trace,accessed `pc->f` here,start of value trace,variable declared,assigned to `pc`] +codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by call to `free()` on `x` here,start of use after lifetime trace,accessed `x` here] +codetoanalyze/cpp/pulse/use_after_free.cpp, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [start of end of lifetime trace,invalidated by call to `free()` on `x` here,start of use after lifetime trace,accessed `*(x)` here] +codetoanalyze/cpp/pulse/vector.cpp, FP_init_fill_then_push_back_loop_ok, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, assign_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::assign()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, clear_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::clear()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, deref_local_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, deref_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::push_back()` on `vec` here,start of use after lifetime trace,accessed `*(y)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,assigned to `y`] +codetoanalyze/cpp/pulse/vector.cpp, emplace_back_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::emplace_back()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::emplace()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, insert_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::insert()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, push_back_loop_bad, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::push_back()` on `&(vec)` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(&(vec),(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, reserve_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::reserve()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`] +codetoanalyze/cpp/pulse/vector.cpp, shrink_to_fit_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [start of end of lifetime trace,invalidated by potentially invalidated by call to `std::vector::shrink_to_fit()` on `vec` here,start of use after lifetime trace,accessed `*(elt)` here,start of value trace,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`]