diff --git a/infer/src/pulse/PulseAbductiveDomain.ml b/infer/src/pulse/PulseAbductiveDomain.ml index ebf68b949..773026c23 100644 --- a/infer/src/pulse/PulseAbductiveDomain.ml +++ b/infer/src/pulse/PulseAbductiveDomain.ml @@ -356,7 +356,7 @@ module PrePost = struct [call_state.astate] starting from address [addr_caller]. Report an error if some invalid addresses are traversed in the process. *) let rec materialize_pre_from_address callee_proc_name call_location access_expr ~pre ~addr_pre - ~addr_caller trace call_state = + ~addr_caller breadcrumbs call_state = let mk_action action = PulseTrace.ViaCall {action; proc_name= callee_proc_name; location= call_location} in @@ -374,7 +374,7 @@ module PrePost = struct | Error invalidated_by -> Error (PulseDiagnostic.AccessToInvalidAddress - {access= access_expr; invalidated_by; accessed_by= action; trace}) + {access= access_expr; invalidated_by; accessed_by= {action; breadcrumbs}}) | Ok astate -> let call_state = {call_state with astate} in Container.fold_result @@ -391,7 +391,7 @@ module PrePost = struct |> Option.value ~default:access_expr in materialize_pre_from_address callee_proc_name call_location access_expr ~pre - ~addr_pre:addr_pre_dest ~addr_caller:addr_caller_dest trace call_state )) + ~addr_pre:addr_pre_dest ~addr_caller:addr_caller_dest breadcrumbs call_state )) |> function Some result -> result | None -> Ok call_state ) @@ -519,8 +519,10 @@ module PrePost = struct let add_call_to_attr proc_name location attr = match (attr : PulseDomain.Attribute.t) with - | Invalid action -> - PulseDomain.Attribute.Invalid (PulseTrace.ViaCall {action; proc_name; location}) + | Invalid trace -> + PulseDomain.Attribute.Invalid + { action= PulseTrace.ViaCall {action= trace.action; proc_name; location} + ; breadcrumbs= trace.breadcrumbs } | MustBeValid _ | AddressOfCppTemporary (_, _) | Closure _ | StdVectorReserve -> attr diff --git a/infer/src/pulse/PulseAbductiveDomain.mli b/infer/src/pulse/PulseAbductiveDomain.mli index 5c013c2cd..9fa3f3c8c 100644 --- a/infer/src/pulse/PulseAbductiveDomain.mli +++ b/infer/src/pulse/PulseAbductiveDomain.mli @@ -46,13 +46,14 @@ module Memory : sig HilExp.AccessExpression.t PulseTrace.action -> AbstractAddress.t -> t - -> (t, PulseInvalidation.t PulseTrace.action) result + -> (t, PulseInvalidation.t PulseTrace.t) result val find_opt : AbstractAddress.t -> t -> PulseDomain.Memory.cell option val set_cell : AbstractAddress.t -> PulseDomain.Memory.cell -> t -> t - val invalidate : AbstractAddress.t -> PulseInvalidation.t PulseTrace.action -> t -> t + val invalidate : + AbstractAddress.t * PulseTrace.breadcrumbs -> PulseInvalidation.t PulseTrace.action -> t -> t val is_std_vector_reserved : AbstractAddress.t -> t -> bool diff --git a/infer/src/pulse/PulseDiagnostic.ml b/infer/src/pulse/PulseDiagnostic.ml index 824d1e73b..831a76928 100644 --- a/infer/src/pulse/PulseDiagnostic.ml +++ b/infer/src/pulse/PulseDiagnostic.ml @@ -11,21 +11,24 @@ module F = Format type t = | AccessToInvalidAddress of { access: HilExp.AccessExpression.t - ; invalidated_by: PulseInvalidation.t PulseTrace.action - ; accessed_by: HilExp.AccessExpression.t PulseTrace.action - ; trace: PulseTrace.breadcrumbs } + ; invalidated_by: PulseInvalidation.t PulseTrace.t + ; accessed_by: HilExp.AccessExpression.t PulseTrace.t } | StackVariableAddressEscape of { variable: Var.t ; trace: PulseTrace.breadcrumbs ; location: Location.t } -let describe_access = PulseTrace.pp_action (Pp.in_backticks HilExp.AccessExpression.pp) +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 describe_invalidation = PulseTrace.pp_action PulseInvalidation.describe let get_location = function | AccessToInvalidAddress {accessed_by} -> - PulseTrace.outer_location_of_action accessed_by + PulseTrace.outer_location_of_action accessed_by.action | StackVariableAddressEscape {location} -> location @@ -34,14 +37,14 @@ 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 *) - let line_of_action action = - let {Location.line; _} = PulseTrace.outer_location_of_action action 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_action invalidated_by in - let access_line = line_of_action accessed_by 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 in + 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 @@ -56,33 +59,15 @@ 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} -> - let add_header_if_some ~title location_opt errlog = - match location_opt with - | None -> - errlog - | Some location -> - add_errlog_header ~title location errlog - in + | AccessToInvalidAddress {accessed_by; invalidated_by} -> let pp_invalid_access f access = F.fprintf f "invalid access to `%a`" HilExp.AccessExpression.pp access in - add_errlog_header ~title:"invalidation part of the trace starts here" - (PulseTrace.outer_location_of_action invalidated_by) - @@ PulseTrace.add_errlog_of_action ~nesting:1 PulseInvalidation.describe invalidated_by - @@ add_errlog_header ~title:"use-after-lifetime part of the trace starts here" - (PulseTrace.outer_location_of_action accessed_by) - @@ PulseTrace.add_errlog_of_action ~nesting:1 pp_invalid_access accessed_by - @@ add_header_if_some ~title:"trace of how the access expression was constructed starts here" - (PulseTrace.start_location_of_breadcrumbs trace) - @@ PulseTrace.add_errlog_of_breadcrumbs ~nesting:1 trace + PulseTrace.add_to_errlog ~header:"invalidation part of the trace starts here" + PulseInvalidation.describe invalidated_by + @@ PulseTrace.add_to_errlog ~header:"use-after-lifetime part of the trace starts here" + pp_invalid_access accessed_by @@ [] | StackVariableAddressEscape {trace; location; _} -> PulseTrace.add_errlog_of_breadcrumbs ~nesting:0 trace @@ -93,6 +78,6 @@ let get_trace = function let get_issue_type = function | AccessToInvalidAddress {invalidated_by} -> - PulseTrace.immediate_of_action invalidated_by |> PulseInvalidation.issue_type_of_cause + PulseTrace.immediate_of_action invalidated_by.action |> PulseInvalidation.issue_type_of_cause | StackVariableAddressEscape _ -> IssueType.stack_variable_address_escape diff --git a/infer/src/pulse/PulseDiagnostic.mli b/infer/src/pulse/PulseDiagnostic.mli index 49783a828..07b379e8a 100644 --- a/infer/src/pulse/PulseDiagnostic.mli +++ b/infer/src/pulse/PulseDiagnostic.mli @@ -11,9 +11,8 @@ open! IStd type t = | AccessToInvalidAddress of { access: HilExp.AccessExpression.t - ; invalidated_by: PulseInvalidation.t PulseTrace.action - ; accessed_by: HilExp.AccessExpression.t PulseTrace.action - ; trace: PulseTrace.breadcrumbs } + ; invalidated_by: PulseInvalidation.t PulseTrace.t + ; accessed_by: HilExp.AccessExpression.t PulseTrace.t } | StackVariableAddressEscape of { variable: Var.t ; trace: PulseTrace.breadcrumbs diff --git a/infer/src/pulse/PulseDomain.ml b/infer/src/pulse/PulseDomain.ml index 60743a3d6..ca4464e8e 100644 --- a/infer/src/pulse/PulseDomain.ml +++ b/infer/src/pulse/PulseDomain.ml @@ -15,7 +15,7 @@ module Invalidation = PulseInvalidation addresses. Otherwise they become a pain to handle when comparing memory states. *) module Attribute = struct type t = - | Invalid of Invalidation.t PulseTrace.action + | Invalid of Invalidation.t PulseTrace.t | MustBeValid of HilExp.AccessExpression.t PulseTrace.action | AddressOfCppTemporary of Var.t * Location.t option | Closure of Typ.Procname.t @@ -27,7 +27,9 @@ module Attribute = struct let to_rank = Variants.to_rank let invalid_rank = - Variants.to_rank (Invalid (Immediate {imm= Invalidation.Nullptr; location= Location.dummy})) + Variants.to_rank + (Invalid + {action= Immediate {imm= Invalidation.Nullptr; location= Location.dummy}; breadcrumbs= []}) let must_be_valid_rank = @@ -44,7 +46,7 @@ module Attribute = struct let pp f = function | Invalid invalidation -> - (PulseTrace.pp_action Invalidation.pp) f invalidation + (PulseTrace.pp Invalidation.pp) f invalidation | MustBeValid action -> F.fprintf f "MustBeValid (read by %a @ %a)" (PulseTrace.pp_action HilExp.AccessExpression.pp) @@ -175,9 +177,10 @@ module Memory : sig val add_attributes : AbstractAddress.t -> Attributes.t -> t -> t - val invalidate : AbstractAddress.t -> Invalidation.t PulseTrace.action -> t -> t + val invalidate : + AbstractAddress.t * PulseTrace.breadcrumbs -> Invalidation.t PulseTrace.action -> t -> t - val check_valid : AbstractAddress.t -> t -> (unit, Invalidation.t PulseTrace.action) result + val check_valid : AbstractAddress.t -> t -> (unit, Invalidation.t PulseTrace.t) result val std_vector_reserve : AbstractAddress.t -> t -> t @@ -240,8 +243,8 @@ end = struct add_attributes address (Attributes.singleton attribute) memory - let invalidate address invalidation memory = - add_attribute address (Attribute.Invalid invalidation) memory + let invalidate (address, breadcrumbs) invalidation memory = + add_attribute address (Attribute.Invalid {action= invalidation; breadcrumbs}) memory let check_valid address memory = diff --git a/infer/src/pulse/PulseDomain.mli b/infer/src/pulse/PulseDomain.mli index 59c1e3e0b..d5bf7803b 100644 --- a/infer/src/pulse/PulseDomain.mli +++ b/infer/src/pulse/PulseDomain.mli @@ -10,7 +10,7 @@ module F = Format module Attribute : sig type t = - | Invalid of PulseInvalidation.t PulseTrace.action + | Invalid of PulseInvalidation.t PulseTrace.t | MustBeValid of HilExp.AccessExpression.t PulseTrace.action | AddressOfCppTemporary of Var.t * Location.t option | Closure of Typ.Procname.t @@ -93,9 +93,10 @@ module Memory : sig val add_attributes : AbstractAddress.t -> Attributes.t -> t -> t - val invalidate : AbstractAddress.t -> PulseInvalidation.t PulseTrace.action -> t -> t + val invalidate : + AbstractAddress.t * PulseTrace.breadcrumbs -> PulseInvalidation.t PulseTrace.action -> t -> t - val check_valid : AbstractAddress.t -> t -> (unit, PulseInvalidation.t PulseTrace.action) result + val check_valid : AbstractAddress.t -> t -> (unit, PulseInvalidation.t PulseTrace.t) result val std_vector_reserve : AbstractAddress.t -> t -> t diff --git a/infer/src/pulse/PulseOperations.ml b/infer/src/pulse/PulseOperations.ml index 2e80f8e0c..5d4273271 100644 --- a/infer/src/pulse/PulseOperations.ml +++ b/infer/src/pulse/PulseOperations.ml @@ -26,11 +26,11 @@ type t = PulseAbductiveDomain.t type 'a access_result = ('a, PulseDiagnostic.t) result (** Check that the address is not known to be invalid *) -let check_addr_access access action (address, trace) astate = +let check_addr_access access action (address, breadcrumbs) astate = Memory.check_valid action address astate |> Result.map_error ~f:(fun invalidated_by -> - PulseDiagnostic.AccessToInvalidAddress {access; invalidated_by; accessed_by= action; trace} - ) + PulseDiagnostic.AccessToInvalidAddress + {access; invalidated_by; accessed_by= {action; breadcrumbs}} ) (** Walk the heap starting from [addr] and following [path]. Stop either at the element before last @@ -192,7 +192,7 @@ let invalidate cause location access_expr astate = materialize_address astate access_expr location >>= fun (astate, addr_trace) -> check_addr_access access_expr (Immediate {imm= access_expr; location}) addr_trace astate - >>| mark_invalid cause (fst addr_trace) + >>| mark_invalid cause addr_trace let invalidate_array_elements cause location access_expr astate = @@ -205,10 +205,10 @@ let invalidate_array_elements cause location access_expr astate = astate | Some (edges, _) -> Memory.Edges.fold - (fun access (dest_addr, _) astate -> + (fun access dest_addr_trace astate -> match (access : Memory.Access.t) with | ArrayAccess _ -> - mark_invalid cause dest_addr astate + mark_invalid cause dest_addr_trace astate | _ -> astate ) edges astate diff --git a/infer/src/pulse/PulseTrace.ml b/infer/src/pulse/PulseTrace.ml index b83bf9564..305f82822 100644 --- a/infer/src/pulse/PulseTrace.ml +++ b/infer/src/pulse/PulseTrace.ml @@ -118,3 +118,25 @@ let add_errlog_of_action ~nesting pp_immediate action errlog = let outer_location_of_action = function Immediate {location} | ViaCall {location} -> location +type 'a t = {action: 'a action; breadcrumbs: breadcrumbs} [@@deriving compare] + +let pp pp_immediate f {action; _} = pp_action pp_immediate f action + +let add_errlog_header ~title location errlog = + let depth = 0 in + let tags = [] in + Errlog.make_trace_element depth location title tags :: errlog + + +let add_to_errlog ~header pp_immediate trace errlog = + let start_location = + match start_location_of_breadcrumbs trace.breadcrumbs with + | Some location -> + location + | None -> + outer_location_of_action trace.action + in + add_errlog_header ~title:header start_location + @@ add_errlog_of_breadcrumbs ~nesting:1 trace.breadcrumbs + @@ add_errlog_of_action ~nesting:1 pp_immediate trace.action + @@ errlog diff --git a/infer/src/pulse/PulseTrace.mli b/infer/src/pulse/PulseTrace.mli index 38d1ca13e..91af3fe11 100644 --- a/infer/src/pulse/PulseTrace.mli +++ b/infer/src/pulse/PulseTrace.mli @@ -28,8 +28,6 @@ val pp_breadcrumbs : F.formatter -> breadcrumbs -> unit val add_errlog_of_breadcrumbs : nesting:int -> breadcrumbs -> Errlog.loc_trace_elem list -> Errlog.loc_trace_elem list -val start_location_of_breadcrumbs : breadcrumbs -> Location.t option - type 'a action = | Immediate of {imm: 'a; location: Location.t} | ViaCall of {action: 'a action; proc_name: Typ.Procname.t; location: Location.t} @@ -41,9 +39,13 @@ val immediate_of_action : 'a action -> 'a val outer_location_of_action : 'a action -> Location.t -val add_errlog_of_action : - nesting:int +type 'a t = {action: 'a action; breadcrumbs: breadcrumbs} [@@deriving compare] + +val pp : (F.formatter -> 'a -> unit) -> F.formatter -> 'a t -> unit + +val add_to_errlog : + header:string -> (F.formatter -> 'a -> unit) - -> 'a action - -> Errlog.loc_trace_elem sexp_list - -> Errlog.loc_trace_elem sexp_list + -> 'a t + -> Errlog.loc_trace_elem list + -> Errlog.loc_trace_elem list diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index 71f0c6746..2bbe8d5ee 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,invalid access to `&(f)` here,trace of how the access expression was constructed starts here,`&(s)` captured as `s`] -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,invalid access to `&(f)` here,trace of how the access expression was constructed starts here,`&(s)` captured as `s`] +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,memory invalidated by `delete` on `y` 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,trace of how the access expression was constructed starts here,assigned to `z`] +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,when calling `may_return_invalid_ptr_ok()` here,memory invalidated by `delete` on `y` here,use-after-lifetime part of the trace starts here,when calling `call_store()` here,when calling `store()` here,invalid access to `y->p` here,trace of how the access expression was constructed starts here,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, [invalidation part of the trace starts here,memory invalidated by `delete` on `result` here,use-after-lifetime part of the trace starts here,invalid access to `*(result)` here,trace of how the access expression was constructed starts here,assigned to `result`] -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,invalid access to `rw.b->f` here,trace of how the access expression was constructed starts here,assigned to `this->b`,returned from call to `ReferenceWrapperHeap::ReferenceWrapperHeap()`] -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,invalid access to `rw.b->f` here,trace of how the access expression was constructed starts here,returned from call to `getwrapperStack()`] +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/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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `s->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `s` here,trace of how the access expression was constructed starts here,assigned to `s`] -codetoanalyze/cpp/pulse/use_after_delete.cpp, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,when calling `Simple` here,invalid access to `__param_0->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -codetoanalyze/cpp/pulse/use_after_delete.cpp, double_delete_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `s` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `s->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,when calling `Simple` here,invalid access to `__param_0->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `s->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here,trace of how the access expression was constructed starts here,variable declared] -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,memory invalidated by `delete` on `alias` here,use-after-lifetime part of the trace starts here,invalid access to `s->f` here,trace of how the access expression was constructed starts here,assigned to `s`] -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,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `alias->f` here,trace of how the access expression was constructed starts here,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, [invalidation part of the trace starts here,memory invalidated by `delete` on `s` here,use-after-lifetime part of the trace starts here,invalid access to `alias->f` here,trace of how the access expression was constructed starts here,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, [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,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here,trace of how the access expression was constructed starts here,variable declared] -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,invalid access to `*(s.f)` here,trace of how the access expression was constructed starts here,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, [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,when calling `~S` here,when calling `__infer_inner_destructor_~S` here,invalid access to `this->f` here,trace of how the access expression was constructed starts here,variable declared] +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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(y)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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,invalid access to `*(elt)` here,trace of how the access expression was constructed starts here,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, [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]