[pulse] traces record how values were constructed

Summary:
Before: the trace would explain how a value was invalidated and
accessed, but not how the value that was invalidated had been
constructed.

Now: `PulseTrace.t` records breadcrumbs of how the value was constructed
in addition to the interproc "action" trace leading to the invalidation
or access action.

Concretely:

```
void bad(X &x) {
  X *y = x;
  X *z = x;
  delete y;
  access(z);
}
```

will produce the trace:

Invalidation part:
y = x
delete y

Access part:
z = x
access(z)
access to z->f inside of access(z)

Before this diff the "Access part" would be missing the "z = x" part of
the trace, so it might be confusing why `z` has anything to do with `y`.

However, such "breadcrumbs" are not recorded in the inter-procedural
part, only the sequence of calls is. This is a trade-off for simplicity,
maybe it's enough for developers maybe it isn't, we'll find out later.

Reviewed By: jberdine

Differential Revision: D15354438

fbshipit-source-id: 8d0aed717
master
Jules Villard 6 years ago committed by Facebook Github Bot
parent 70d38cea77
commit 6364199b94

@ -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

@ -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

@ -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

@ -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

@ -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 =

@ -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

@ -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

@ -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

@ -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

@ -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<int*>::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<int>::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 `<placement new>(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 `<placement new>(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 `<placement new>(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]

Loading…
Cancel
Save