diff --git a/infer/src/IR/HilExp.ml b/infer/src/IR/HilExp.ml index 02b654108..a9166d5fd 100644 --- a/infer/src/IR/HilExp.ml +++ b/infer/src/IR/HilExp.ml @@ -351,6 +351,12 @@ module AccessExpression = struct init | Sizeof (_, exp_opt) -> fold_vars_exp_opt exp_opt ~init ~f + + + let to_source_string access_expr = + (* should probably eventually check more than just the base but yolo *) + let var, _ = get_base access_expr in + if Var.appears_in_source_code var then Some (F.asprintf "%a" pp access_expr) else None end let rec get_typ tenv = function diff --git a/infer/src/IR/HilExp.mli b/infer/src/IR/HilExp.mli index 2c0dccb04..e846f6add 100644 --- a/infer/src/IR/HilExp.mli +++ b/infer/src/IR/HilExp.mli @@ -90,6 +90,10 @@ module AccessExpression : sig val fold_vars : (t, Var.t, 'accum) Container.fold val add_access : _ Access.t -> t -> t option + + val to_source_string : t -> string option + (** get a string representation of the access expression in terms of symbols that appear in the + program, to show to the user *) end val pp : F.formatter -> t -> unit diff --git a/infer/src/istd/Pp.mli b/infer/src/istd/Pp.mli index ceadd3ff3..2a660ba6d 100644 --- a/infer/src/istd/Pp.mli +++ b/infer/src/istd/Pp.mli @@ -101,4 +101,4 @@ val pair : -> 'a * 'b -> unit -val in_backticks : (F.formatter -> 'a -> unit) -> F.formatter -> 'a -> unit +val in_backticks : (F.formatter -> 'a -> unit) -> F.formatter -> 'a -> unit [@@warning "-32"] diff --git a/infer/src/pulse/PulseDiagnostic.ml b/infer/src/pulse/PulseDiagnostic.ml index 831a76928..8067aa32c 100644 --- a/infer/src/pulse/PulseDiagnostic.ml +++ b/infer/src/pulse/PulseDiagnostic.ml @@ -18,14 +18,6 @@ type t = ; trace: PulseTrace.breadcrumbs ; location: Location.t } -let describe_access f trace = - PulseTrace.pp_action (Pp.in_backticks HilExp.AccessExpression.pp) f trace.PulseTrace.action - - -let describe_invalidation f trace = - PulseTrace.pp_action PulseInvalidation.describe f trace.PulseTrace.action - - let get_location = function | AccessToInvalidAddress {accessed_by} -> PulseTrace.outer_location_of_action accessed_by.action @@ -35,22 +27,80 @@ let get_location = function let get_message = function | AccessToInvalidAddress {access; accessed_by; invalidated_by; _} -> - (* TODO: [access] might be something irrelevant to the user, shouldn't print it in that case - *) + (* The goal is to get one of the following messages depending on the scenario: + + 42: delete x; return x->f + "`x->f` accesses `x`, which was invalidated at line 42 by `delete` on `x`" + + 42: bar(x); return x->f + "`x->f` accesses `x`, which was invalidated at line 42 by `delete` on `x` in call to `bar`" + + 42: bar(x); foo(x); + "call to `foo` eventually accesses `x->f` but `x` was invalidated at line 42 by `delete` on `x` in call to `bar`" + + If we don't have "x->f" but instead some non-user-visible expression, then + "access to `x`, which was invalidated at line 42 by `delete` on `x`" + + Likewise if we don't have "x" in the second part but instead some non-user-visible expression, then + "`x->f` accesses `x`, which was invalidated at line 42 by `delete`" + *) + let pp_access_trace invalidated f trace = + match trace.PulseTrace.action with + | Immediate {imm= access; _} -> ( + match HilExp.AccessExpression.to_source_string access with + | Some access_s when HilExp.AccessExpression.equal access invalidated -> + F.fprintf f "`%s` " access_s + | Some access_s -> ( + match HilExp.AccessExpression.to_source_string invalidated with + | Some invalidated_s -> + F.fprintf f "`%s` accesses `%s`, which " access_s invalidated_s + | None -> + F.fprintf f "access to `%s`, which " access_s ) + | None -> ( + match HilExp.AccessExpression.to_source_string invalidated with + | Some invalidated_s -> + F.fprintf f "`%s` " invalidated_s + | None -> + F.fprintf f "accessing memory that " ) ) + | ViaCall {action; proc_name; _} -> ( + let access_and_invalidated_s = + match + ( HilExp.AccessExpression.to_source_string (PulseTrace.immediate_of_action action) + , HilExp.AccessExpression.to_source_string invalidated ) + with + | Some access_s, Some invalidated_s -> + Some (access_s, invalidated_s) + | Some s, None | None, Some s -> + Some (s, s) + | None, None -> + None + in + match access_and_invalidated_s with + | Some (access_s, invalidated_s) -> + F.fprintf f "call to `%a` eventually accesses `%s` but `%s` " Typ.Procname.describe + proc_name access_s invalidated_s + | None -> + F.fprintf f "call to `%a` eventually accesses `%a`, which " Typ.Procname.describe + proc_name HilExp.AccessExpression.pp invalidated ) + in + let pp_invalidation_trace line f trace = + match trace.PulseTrace.action with + | Immediate {imm= invalidation; _} -> + F.fprintf f "%a on line %d" PulseInvalidation.describe invalidation line + | ViaCall {action; proc_name; _} -> + F.fprintf f "%a on line %d indirectly during the call to `%a`" + PulseInvalidation.describe + (PulseTrace.immediate_of_action action) + line Typ.Procname.describe proc_name + in let line_of_trace trace = let {Location.line; _} = PulseTrace.outer_location_of_action trace.PulseTrace.action in line in let invalidation_line = line_of_trace invalidated_by in - let access_line = line_of_trace accessed_by in - let pp_indirect_access f = - let erroneous_access = PulseTrace.immediate_of_action accessed_by.action in - if not (HilExp.AccessExpression.equal erroneous_access access) then - F.fprintf f " via %a" describe_access accessed_by - in - F.asprintf "access to `%a`%t at line %d is to %a on line %d" HilExp.AccessExpression.pp - access pp_indirect_access access_line describe_invalidation invalidated_by - invalidation_line + F.asprintf "%a%a" (pp_access_trace access) accessed_by + (pp_invalidation_trace invalidation_line) + invalidated_by | StackVariableAddressEscape {variable; _} -> let pp_var f var = if Var.is_cpp_temporary var then F.pp_print_string f "C++ temporary" @@ -61,13 +111,12 @@ let get_message = function let get_trace = function | AccessToInvalidAddress {accessed_by; invalidated_by} -> - let pp_invalid_access f access = - F.fprintf f "invalid access to `%a`" HilExp.AccessExpression.pp access - in PulseTrace.add_to_errlog ~header:"invalidation part of the trace starts here" - PulseInvalidation.describe invalidated_by + (fun f invalidation -> F.fprintf f "memory %a" PulseInvalidation.describe invalidation) + invalidated_by @@ PulseTrace.add_to_errlog ~header:"use-after-lifetime part of the trace starts here" - pp_invalid_access accessed_by + (fun f access -> F.fprintf f "invalid access to `%a`" HilExp.AccessExpression.pp access) + accessed_by @@ [] | StackVariableAddressEscape {trace; location; _} -> PulseTrace.add_errlog_of_breadcrumbs ~nesting:0 trace diff --git a/infer/src/pulse/PulseInvalidation.ml b/infer/src/pulse/PulseInvalidation.ml index dbf0473aa..fbf852ff9 100644 --- a/infer/src/pulse/PulseInvalidation.ml +++ b/infer/src/pulse/PulseInvalidation.ml @@ -60,21 +60,21 @@ let issue_type_of_cause = function let describe f = function | CFree access_expr -> - F.fprintf f "memory invalidated by call to `free()` on `%a`" HilExp.AccessExpression.pp + F.fprintf f "was invalidated by call to `free()` on `%a`" HilExp.AccessExpression.pp access_expr | CppDelete access_expr -> - F.fprintf f "memory invalidated by `delete` on `%a`" HilExp.AccessExpression.pp access_expr + F.fprintf f "was invalidated by `delete` on `%a`" HilExp.AccessExpression.pp access_expr | GoneOutOfScope (pvar, typ) -> let pp_var f pvar = if Pvar.is_cpp_temporary pvar then - F.fprintf f "C++ temporary of type `%a`" (Typ.pp_full Pp.text) typ - else F.fprintf f "stack variable `%a`" Pvar.pp_value pvar + F.fprintf f "is the address of a C++ temporary of type `%a`" (Typ.pp_full Pp.text) typ + else F.fprintf f "is the address of a stack variable `%a`" Pvar.pp_value pvar in - F.fprintf f "address of %a whose lifetime has ended" pp_var pvar + F.fprintf f "%a whose lifetime has ended" pp_var pvar | Nullptr -> - F.fprintf f "the null pointer" + F.fprintf f "is the null pointer" | StdVector (std_vector_f, access_expr) -> - F.fprintf f "memory potentially invalidated by call to `%a()` on `%a`" pp_std_vector_function + F.fprintf f "was potentially invalidated by `%a()` on `%a`" pp_std_vector_function std_vector_f HilExp.AccessExpression.pp access_expr diff --git a/infer/src/pulse/PulseOperations.ml b/infer/src/pulse/PulseOperations.ml index 5d4273271..83a9c0b9c 100644 --- a/infer/src/pulse/PulseOperations.ml +++ b/infer/src/pulse/PulseOperations.ml @@ -62,6 +62,9 @@ let rec walk ~dereference_to_ignore access_expr action ~on_last addr_trace path Option.map ~f:(fun index -> max 0 (index - 1)) dereference_to_ignore in let astate, addr_trace' = Memory.materialize_edge (fst addr_trace) a astate in + let access_expr = + HilExp.AccessExpression.add_access a access_expr |> Option.value ~default:access_expr + in walk access_expr ~dereference_to_ignore action ~on_last addr_trace' path astate @@ -107,10 +110,11 @@ let rec to_accesses location access_expr astate = (** add addresses to the state to give an address to the destination of the given access path *) and walk_access_expr ~on_last astate access_expr location = to_accesses location access_expr astate - >>= fun (astate, (access_var, _), access_list) -> + >>= fun (astate, base, access_list) -> let dereference_to_ignore = if ends_with_addressof access_expr then last_dereference access_list else None in + let access_var, _ = base in if Config.write_html then L.d_printfln "Accessing %a -> [%a]" Var.pp access_var (Pp.seq ~sep:"," Memory.Access.pp) @@ -134,7 +138,9 @@ and walk_access_expr ~on_last astate access_expr location = Ok (astate, base_addr_trace) | _ -> let action = PulseTrace.Immediate {imm= access_expr; location} in - walk access_expr ~dereference_to_ignore action ~on_last base_addr_trace + walk + (HilExp.AccessExpression.base base) + ~dereference_to_ignore action ~on_last base_addr_trace (HilExp.Access.Dereference :: access_list) astate ) diff --git a/infer/src/pulse/PulseTrace.ml b/infer/src/pulse/PulseTrace.ml index 305f82822..b16a242f8 100644 --- a/infer/src/pulse/PulseTrace.ml +++ b/infer/src/pulse/PulseTrace.ml @@ -82,13 +82,6 @@ type 'a action = | ViaCall of {action: 'a action; proc_name: Typ.Procname.t; location: Location.t} [@@deriving compare] -let pp_action pp_immediate fmt = function - | Immediate {imm; _} -> - pp_immediate fmt imm - | ViaCall {proc_name; _} -> - F.fprintf fmt "call to `%a`" Typ.Procname.describe proc_name - - let rec immediate_of_action = function | Immediate {imm; _} -> imm @@ -96,6 +89,14 @@ let rec immediate_of_action = function immediate_of_action action +let pp_action pp_immediate fmt = function + | Immediate {imm; _} -> + pp_immediate fmt imm + | ViaCall {proc_name; action; _} -> + F.fprintf fmt "%a in call to `%a`" pp_immediate (immediate_of_action action) + Typ.Procname.describe proc_name + + let add_errlog_of_action ~nesting pp_immediate action errlog = let rec aux ~nesting rev_errlog action = match action with diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index d7ec974a6..1da54140e 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp @@ -1,46 +1,46 @@ -codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_branch_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by `delete` on `ptr` here,use-after-lifetime part of the trace starts here,invalid access to `*ptr` here] -codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by `delete` on `ptr` here,use-after-lifetime part of the trace starts here,invalid access to `ptr` here] -codetoanalyze/cpp/pulse/closures.cpp, implicit_ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,address of stack variable `s` whose lifetime has ended here,use-after-lifetime part of the trace starts here,`&s` captured as `s`,invalid access to `&f` here] -codetoanalyze/cpp/pulse/closures.cpp, ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,address of stack variable `s` whose lifetime has ended here,use-after-lifetime part of the trace starts here,`&s` captured as `s`,invalid access to `&f` here] -codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `templated_wrapper_delete_ok` here,memory invalidated by `delete` on `a` here,use-after-lifetime part of the trace starts here,when calling `templated_wrapper_access_ok` here,invalid access to `a->f` here] -codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `templated_wrapper_delete_ok` here,memory invalidated by `delete` on `a` here,use-after-lifetime part of the trace starts here,when calling `templated_wrapper_access_ok` here,invalid access to `a->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_aliased_then_read_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `y`,memory invalidated by `delete` on `y` here,use-after-lifetime part of the trace starts here,assigned to `z`,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_inner_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `wraps_delete_inner()` here,memory invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_read_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `wraps_delete()` here,when calling `wraps_delete_inner()` here,memory invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] -codetoanalyze/cpp/pulse/interprocedural.cpp, feed_invalid_into_access_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `y`,when calling `may_return_invalid_ptr_ok()` here,memory invalidated by `delete` on `y` here,use-after-lifetime part of the trace starts here,assigned to `y`,assigned to `return`,returned from call to `may_return_invalid_ptr_ok()`,assigned to `y`,when calling `call_store()` here,when calling `store()` here,invalid access to `y->p` here] -codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_bad, 12, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `result`,memory invalidated by `delete` on `result` here,use-after-lifetime part of the trace starts here,assigned to `result`,invalid access to `*result` here] -codetoanalyze/cpp/pulse/reference_wrapper.cpp, reference_wrapper_heap_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `getwrapperHeap()` here,when calling `~WrapsB` here,when calling `__infer_inner_destructor_~WrapsB` here,memory invalidated by `delete` on `this->b` here,use-after-lifetime part of the trace starts here,assigned to `this->b`,returned from call to `ReferenceWrapperHeap::ReferenceWrapperHeap()`,invalid access to `rw.b->f` here] -codetoanalyze/cpp/pulse/reference_wrapper.cpp, reference_wrapper_stack_bad, 2, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `getwrapperStack()` here,address of stack variable `b` whose lifetime has ended here,use-after-lifetime part of the trace starts here,returned from call to `getwrapperStack()`,invalid access to `rw.b->f` here] +codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_branch_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory was invalidated by `delete` on `ptr` here,use-after-lifetime part of the trace starts here,invalid access to `*ptr` here] +codetoanalyze/cpp/pulse/basics.cpp, multiple_invalidations_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory was invalidated by `delete` on `ptr` here,use-after-lifetime part of the trace starts here,invalid access to `ptr` here] +codetoanalyze/cpp/pulse/closures.cpp, implicit_ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,memory is the address of a stack variable `s` whose lifetime has ended here,use-after-lifetime part of the trace starts here,`&s` captured as `s`,invalid access to `&f` here] +codetoanalyze/cpp/pulse/closures.cpp, ref_capture_destroy_invoke_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,memory is the address of a stack variable `s` whose lifetime has ended here,use-after-lifetime part of the trace starts here,`&s` captured as `s`,invalid access to `&f` here] +codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `templated_wrapper_delete_ok` here,memory was invalidated by `delete` on `a` here,use-after-lifetime part of the trace starts here,when calling `templated_wrapper_access_ok` here,invalid access to `a->f` here] +codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `templated_wrapper_delete_ok` here,memory was invalidated by `delete` on `a` here,use-after-lifetime part of the trace starts here,when calling `templated_wrapper_access_ok` here,invalid access to `a->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_aliased_then_read_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `y`,memory was invalidated by `delete` on `y` here,use-after-lifetime part of the trace starts here,assigned to `z`,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_inner_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `wraps_delete_inner()` here,memory was invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_read_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory was invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, delete_then_write_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `wraps_delete()` here,when calling `wraps_delete_inner()` here,memory was invalidated by `delete` on `x` here,use-after-lifetime part of the trace starts here,when calling `wraps_read()` here,when calling `wraps_read_inner()` here,invalid access to `x->f` here] +codetoanalyze/cpp/pulse/interprocedural.cpp, feed_invalid_into_access_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `y`,when calling `may_return_invalid_ptr_ok()` here,memory was invalidated by `delete` on `y` here,use-after-lifetime part of the trace starts here,assigned to `y`,assigned to `return`,returned from call to `may_return_invalid_ptr_ok()`,assigned to `y`,when calling `call_store()` here,when calling `store()` here,invalid access to `y->p` here] +codetoanalyze/cpp/pulse/join.cpp, invalidate_node_alias_bad, 12, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `result`,memory was invalidated by `delete` on `result` here,use-after-lifetime part of the trace starts here,assigned to `result`,invalid access to `*result` here] +codetoanalyze/cpp/pulse/reference_wrapper.cpp, reference_wrapper_heap_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `getwrapperHeap()` here,when calling `~WrapsB` here,when calling `__infer_inner_destructor_~WrapsB` here,memory was invalidated by `delete` on `this->b` here,use-after-lifetime part of the trace starts here,assigned to `this->b`,returned from call to `ReferenceWrapperHeap::ReferenceWrapperHeap()`,invalid access to `rw.b->f` here] +codetoanalyze/cpp/pulse/reference_wrapper.cpp, reference_wrapper_stack_bad, 2, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `getwrapperStack()` here,memory is the address of a stack variable `b` whose lifetime has ended here,use-after-lifetime part of the trace starts here,returned from call to `getwrapperStack()`,invalid access to `rw.b->f` here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_literal_stack_reference_bad, 0, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [C++ temporary created,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_stack_pointer_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable declared,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference1_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [C++ temporary created,assigned to `x`,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference2_bad, 3, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [C++ temporary created,assigned to `x`,assigned to `y`,returned here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,when calling `Simple` here,invalid access to `__param_0->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, double_delete_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, reassign_field_of_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_branch_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,when calling `Simple` here,invalid access to `__param_0->f` here] -codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_loop_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::double_destructor_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing1_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`,memory invalidated by `delete` on `alias` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`,invalid access to `alias->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing3_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,assigned to `alias`,invalid access to `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, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_destructor_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,assigned to `this->f`,returned from call to `use_after_destructor::S::S()`,invalid access to `*(s.f)` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope1_bad, 7, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] -codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope4_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,address of stack variable `c` whose lifetime has ended here,use-after-lifetime part of the trace starts here,invalid access to `pc->f` here] -codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_global_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `free_global_pointer_ok()` here,memory invalidated by call to `free()` on `global_pointer` here,use-after-lifetime part of the trace starts here,when calling `free_global_pointer_ok()` here,invalid access to `global_pointer` here] -codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by call to `free()` on `x` here,use-after-lifetime part of the trace starts here,invalid access to `x` here] -codetoanalyze/cpp/pulse/use_after_free.cpp, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by call to `free()` on `x` here,use-after-lifetime part of the trace starts here,invalid access to `*x` here] -codetoanalyze/cpp/pulse/vector.cpp, assign_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::assign()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, clear_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::clear()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, deref_local_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::push_back()` on `&vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(&vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, deref_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::push_back()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,assigned to `y`,invalid access to `*y` here] -codetoanalyze/cpp/pulse/vector.cpp, emplace_back_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::emplace_back()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::emplace()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, insert_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::insert()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, push_back_loop_bad, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::push_back()` on `&vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(&vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, reserve_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::reserve()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] -codetoanalyze/cpp/pulse/vector.cpp, shrink_to_fit_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory potentially invalidated by call to `std::vector::shrink_to_fit()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,when calling `Simple` here,invalid access to `__param_0->f` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, double_delete_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, reassign_field_of_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_branch_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,when calling `Simple` here,invalid access to `__param_0->f` here] +codetoanalyze/cpp/pulse/use_after_delete.cpp, use_in_loop_bad, 4, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::double_destructor_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory was invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing1_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`,memory was invalidated by `delete` on `alias` here,use-after-lifetime part of the trace starts here,assigned to `s`,invalid access to `s->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing2_bad, 5, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,returned from call to `(sizeof(use_after_destructor::S),s)`,assigned to `alias`,invalid access to `alias->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::placement_new_aliasing3_bad, 6, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned to `s`,memory was invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,assigned to `s`,assigned to `alias`,invalid access to `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, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory was invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_destructor_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory was invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,assigned to `this->f`,returned from call to `use_after_destructor::S::S()`,invalid access to `*(s.f)` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope1_bad, 7, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,memory was invalidated by `delete` on `this->f` here,use-after-lifetime part of the trace starts here,variable declared,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here] +codetoanalyze/cpp/pulse/use_after_destructor.cpp, use_after_destructor::use_after_scope4_bad, 6, USE_AFTER_LIFETIME, no_bucket, ERROR, [invalidation part of the trace starts here,memory is the address of a stack variable `c` whose lifetime has ended here,use-after-lifetime part of the trace starts here,invalid access to `pc->f` here] +codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_global_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `free_global_pointer_ok()` here,memory was invalidated by call to `free()` on `global_pointer` here,use-after-lifetime part of the trace starts here,when calling `free_global_pointer_ok()` here,invalid access to `global_pointer` here] +codetoanalyze/cpp/pulse/use_after_free.cpp, double_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,memory was invalidated by call to `free()` on `x` here,use-after-lifetime part of the trace starts here,invalid access to `x` here] +codetoanalyze/cpp/pulse/use_after_free.cpp, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,memory was invalidated by call to `free()` on `x` here,use-after-lifetime part of the trace starts here,invalid access to `*x` here] +codetoanalyze/cpp/pulse/vector.cpp, assign_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::assign()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, clear_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::clear()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, deref_local_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::push_back()` on `&vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(&vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, deref_vector_element_after_push_back_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::push_back()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,assigned to `y`,invalid access to `*y` here] +codetoanalyze/cpp/pulse/vector.cpp, emplace_back_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::emplace_back()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::emplace()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, insert_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::insert()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, push_back_loop_bad, 6, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::push_back()` on `&vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(&vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, reserve_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::reserve()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here] +codetoanalyze/cpp/pulse/vector.cpp, shrink_to_fit_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,memory was potentially invalidated by `std::vector::shrink_to_fit()` on `vec` here,use-after-lifetime part of the trace starts here,returned from call to `std::vector::at(vec,(unsigned long) 1)`,assigned to `elt`,invalid access to `*elt` here]