[pulse] Revise trace of uninitialized value check

Summary: This diff revises the trace generation of the uninitialized value checker, by introducing a new diagnostics for it.

Reviewed By: jvillard

Differential Revision: D25433775

fbshipit-source-id: 1279c0de4
master
Sungkeun Cho 4 years ago committed by Facebook GitHub Bot
parent 0980bbe2b3
commit 3685cc6fdd

@ -325,25 +325,20 @@ let set_uninitialized_post src typ location (post : PostDomain.t) =
match typ.Typ.desc with
| Tint _ | Tfloat _ | Tptr _ ->
let {stack; attrs} = (post :> base_domain) in
let stack, addr, history =
let stack, addr =
match src with
| `LocalDecl (pvar, addr_opt) ->
let history = [ValueHistory.VariableDeclared (pvar, location)] in
let stack, addr =
match addr_opt with
| None ->
let addr = AbstractValue.mk_fresh () in
(BaseStack.add (Var.of_pvar pvar) (addr, history) stack, addr)
| Some addr ->
(stack, addr)
in
(stack, addr, history)
| `Malloc (addr, history) ->
(stack, addr, history)
in
let attrs =
BaseAddressAttributes.add_one addr (Uninitialized (Immediate {location; history})) attrs
| `LocalDecl (pvar, addr_opt) -> (
match addr_opt with
| None ->
let addr = AbstractValue.mk_fresh () in
let history = [ValueHistory.VariableDeclared (pvar, location)] in
(BaseStack.add (Var.of_pvar pvar) (addr, history) stack, addr)
| Some addr ->
(stack, addr) )
| `Malloc addr ->
(stack, addr)
in
let attrs = BaseAddressAttributes.add_one addr Uninitialized attrs in
PostDomain.update ~stack ~attrs post
| Tstruct _ ->
(* TODO: set uninitialized attributes for fields *)

@ -126,7 +126,7 @@ module AddressAttributes : sig
val check_valid : Trace.t -> AbstractValue.t -> t -> (t, Invalidation.t * Trace.t) result
val check_initialized : Trace.t -> AbstractValue.t -> t -> (t, Trace.t) result
val check_initialized : Trace.t -> AbstractValue.t -> t -> (t, unit) result
val invalidate : AbstractValue.t * ValueHistory.t -> Invalidation.t -> Location.t -> t -> t
@ -188,8 +188,7 @@ val initialize : AbstractValue.t -> t -> t
val set_uninitialized :
[ `LocalDecl of Pvar.t * AbstractValue.t option
(** the second optional parameter is for the address of the variable *)
| `Malloc of AbstractValue.t * ValueHistory.t
(** the address parameter is a newly allocated address *) ]
| `Malloc of AbstractValue.t (** the address parameter is a newly allocated address *) ]
-> Typ.t
-> Location.t
-> t

@ -35,7 +35,7 @@ module Attribute = struct
| MustBeInitialized of Trace.t
| MustBeValid of Trace.t
| StdVectorReserve
| Uninitialized of Trace.t
| Uninitialized
| WrittenTo of Trace.t
[@@deriving compare, variants]
@ -72,7 +72,7 @@ module Attribute = struct
let end_of_collection_rank = Variants.to_rank EndOfCollection
let uninitialized_rank = Variants.to_rank (Uninitialized dummy_trace)
let uninitialized_rank = Variants.to_rank Uninitialized
let must_be_initialized_rank = Variants.to_rank (MustBeInitialized dummy_trace)
@ -108,10 +108,8 @@ module Attribute = struct
F.fprintf f "MustBeValid %a" (Trace.pp ~pp_immediate:(pp_string_if_debug "access")) trace
| StdVectorReserve ->
F.pp_print_string f "std::vector::reserve()"
| Uninitialized trace ->
F.fprintf f "Uninitialized %a"
(Trace.pp ~pp_immediate:(pp_string_if_debug "declaration"))
trace
| Uninitialized ->
F.pp_print_string f "Uninitialized"
| WrittenTo trace ->
F.fprintf f "WrittenTo %a" (Trace.pp ~pp_immediate:(pp_string_if_debug "mutation")) trace
end
@ -167,6 +165,8 @@ module Attributes = struct
|| Option.is_some (Set.find_rank attrs Attribute.invalid_rank)
let is_uninitialized attrs = Set.find_rank attrs Attribute.uninitialized_rank |> Option.is_some
let get_allocation attrs =
Set.find_rank attrs Attribute.allocated_rank
|> Option.map ~f:(fun attr ->
@ -181,13 +181,6 @@ module Attributes = struct
typ )
let get_uninitialized attrs =
Set.find_rank attrs Attribute.uninitialized_rank
|> Option.map ~f:(fun attr ->
let[@warning "-8"] (Attribute.Uninitialized trace) = attr in
trace )
let get_must_be_initialized attrs =
Set.find_rank attrs Attribute.must_be_initialized_rank
|> Option.map ~f:(fun attr ->
@ -211,7 +204,7 @@ let is_suitable_for_pre = function
| EndOfCollection
| Invalid _
| StdVectorReserve
| Uninitialized _
| Uninitialized
| WrittenTo _ ->
false
@ -223,8 +216,6 @@ let map_trace ~f = function
Invalid (invalidation, f trace)
| MustBeValid trace ->
MustBeValid (f trace)
| Uninitialized trace ->
Uninitialized (f trace)
| WrittenTo trace ->
WrittenTo (f trace)
| MustBeInitialized trace ->
@ -234,5 +225,6 @@ let map_trace ~f = function
| Closure _
| DynamicType _
| EndOfCollection
| StdVectorReserve ) as attr ->
| StdVectorReserve
| Uninitialized ) as attr ->
attr

@ -22,7 +22,7 @@ type t =
| MustBeInitialized of Trace.t
| MustBeValid of Trace.t
| StdVectorReserve
| Uninitialized of Trace.t
| Uninitialized
| WrittenTo of Trace.t
[@@deriving compare]
@ -56,7 +56,7 @@ module Attributes : sig
val is_std_vector_reserved : t -> bool
val get_uninitialized : t -> Trace.t option
val is_uninitialized : t -> bool
val get_must_be_initialized : t -> Trace.t option
end

@ -87,11 +87,8 @@ let check_valid address attrs =
let check_initialized address attrs =
L.d_printfln "Checking if %a is initialized" AbstractValue.pp address ;
match Graph.find_opt address attrs |> Option.bind ~f:Attributes.get_uninitialized with
| Some trace ->
Error trace
| None ->
Ok ()
if Graph.find_opt address attrs |> Option.exists ~f:Attributes.is_uninitialized then Error ()
else Ok ()
let get_attribute getter address attrs =
@ -108,11 +105,9 @@ let remove_allocation_attr address memory =
let initialize address attrs =
match get_attribute Attributes.get_uninitialized address attrs with
| Some trace ->
remove_one address (Attribute.Uninitialized trace) attrs
| None ->
attrs
if Graph.find_opt address attrs |> Option.exists ~f:Attributes.is_uninitialized then
remove_one address Attribute.Uninitialized attrs
else attrs
let get_closure_proc_name = get_attribute Attributes.get_closure_proc_name

@ -31,7 +31,7 @@ val fold : (AbstractValue.t -> Attributes.t -> 'a -> 'a) -> t -> 'a -> 'a
val check_valid : AbstractValue.t -> t -> (unit, Invalidation.t * Trace.t) result
val check_initialized : AbstractValue.t -> t -> (unit, Trace.t) result
val check_initialized : AbstractValue.t -> t -> (unit, unit) result
val invalidate : AbstractValue.t * ValueHistory.t -> Invalidation.t -> Location.t -> t -> t

@ -19,23 +19,40 @@ type access_to_invalid_address =
; access_trace: Trace.t }
[@@deriving equal]
type read_uninitialized_value = {calling_context: (CallEvent.t * Location.t) list; trace: Trace.t}
[@@deriving equal]
let yojson_of_access_to_invalid_address = [%yojson_of: _]
let yojson_of_read_uninitialized_value = [%yojson_of: _]
type t =
| AccessToInvalidAddress of access_to_invalid_address
| MemoryLeak of {procname: Procname.t; allocation_trace: Trace.t; location: Location.t}
| ReadUninitializedValue of read_uninitialized_value
| StackVariableAddressEscape of {variable: Var.t; history: ValueHistory.t; location: Location.t}
[@@deriving equal]
let get_location = function
| AccessToInvalidAddress {calling_context= []; access_trace} ->
| AccessToInvalidAddress {calling_context= []; access_trace}
| ReadUninitializedValue {calling_context= []; trace= access_trace} ->
Trace.get_outer_location access_trace
| AccessToInvalidAddress {calling_context= (_, location) :: _} ->
| AccessToInvalidAddress {calling_context= (_, location) :: _}
| ReadUninitializedValue {calling_context= (_, location) :: _} ->
(* report at the call site that triggers the bug *) location
| MemoryLeak {location} | StackVariableAddressEscape {location} ->
location
(* whether the [calling_context + trace] starts with a call or contains only an immediate event *)
let immediate_or_first_call calling_context (trace : Trace.t) =
match (calling_context, trace) with
| [], Immediate _ ->
`Immediate
| (f, _) :: _, _ | [], ViaCall {f; _} ->
`Call f
let get_message = function
| AccessToInvalidAddress {calling_context; invalidation; invalidation_trace; access_trace} ->
(* The goal is to get one of the following messages depending on the scenario:
@ -55,14 +72,6 @@ let get_message = function
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`"
*)
(* whether the [calling_context + trace] starts with a call or contains only an immediate event *)
let immediate_or_first_call calling_context (trace : Trace.t) =
match (calling_context, trace) with
| [], Immediate _ ->
`Immediate
| (f, _) :: _, _ | [], ViaCall {f; _} ->
`Call f
in
let pp_access_trace fmt (trace : Trace.t) =
match immediate_or_first_call calling_context trace with
| `Immediate ->
@ -101,6 +110,16 @@ let get_message = function
F.asprintf
"memory dynamically allocated at line %d %a, is not freed after the last access at %a"
allocation_line pp_allocation_trace allocation_trace Location.pp location
| ReadUninitializedValue {calling_context; trace} ->
let pp_trace fmt (trace : Trace.t) =
let {Location.line} = Trace.get_outer_location trace in
match immediate_or_first_call calling_context trace with
| `Immediate ->
F.fprintf fmt "on line %d" line
| `Call f ->
F.fprintf fmt "during the call to %a on line %d" CallEvent.describe f line
in
F.asprintf "uninitialized value is read %a" pp_trace trace
| StackVariableAddressEscape {variable; _} ->
let pp_var f var =
if Var.is_cpp_temporary var then F.pp_print_string f "C++ temporary"
@ -115,21 +134,24 @@ let add_errlog_header ~title location errlog =
Errlog.make_trace_element depth location title tags :: errlog
let get_trace_calling_context calling_context errlog =
match calling_context with
| [] ->
errlog
| (_, first_call_loc) :: _ ->
add_errlog_header ~title:"calling context starts here" first_call_loc
@@ ( List.fold calling_context ~init:(errlog, 0) ~f:(fun (errlog, depth) (call, loc) ->
( Errlog.make_trace_element depth loc
(F.asprintf "in call to %a" CallEvent.pp call)
[]
:: errlog
, depth + 1 ) )
|> fst )
let get_trace = function
| AccessToInvalidAddress {calling_context; invalidation; invalidation_trace; access_trace} ->
(fun errlog ->
match calling_context with
| [] ->
errlog
| (_, first_call_loc) :: _ ->
add_errlog_header ~title:"calling context starts here" first_call_loc
@@ ( List.fold calling_context ~init:(errlog, 0) ~f:(fun (errlog, depth) (call, loc) ->
( Errlog.make_trace_element depth loc
(F.asprintf "in call to %a" CallEvent.pp call)
[]
:: errlog
, depth + 1 ) )
|> fst ) )
get_trace_calling_context calling_context
@@
let start_location = Trace.get_start_location invalidation_trace in
add_errlog_header ~title:"invalidation part of the trace starts here" start_location
@ -151,6 +173,12 @@ let get_trace = function
~pp_immediate:(fun fmt -> F.pp_print_string fmt "allocation part of the trace ends here")
allocation_trace
@@ [Errlog.make_trace_element 0 location "memory becomes unreachable here" []]
| ReadUninitializedValue {calling_context; trace} ->
get_trace_calling_context calling_context
@@ Trace.add_to_errlog ~nesting:0
~pp_immediate:(fun fmt -> F.pp_print_string fmt "read to uninitialized value occurs here")
trace
@@ []
| StackVariableAddressEscape {history; location; _} ->
ValueHistory.add_to_errlog ~nesting:0 history
@@
@ -163,5 +191,7 @@ let get_issue_type = function
Invalidation.issue_type_of_cause invalidation
| MemoryLeak _ ->
IssueType.pulse_memory_leak
| ReadUninitializedValue _ ->
IssueType.uninitialized_value_pulse
| StackVariableAddressEscape _ ->
IssueType.stack_variable_address_escape

@ -24,10 +24,20 @@ type access_to_invalid_address =
invalidated in [invalidation_trace] without further assumptions *) }
[@@deriving equal, yojson_of]
type read_uninitialized_value =
{ calling_context: (CallEvent.t * Location.t) list
(** the list of function calls leading to the issue being realised, which is an additional
common prefix to the traces in the record *)
; trace: Trace.t
(** assuming we are in the calling context, the trace leads to read of the uninitialized
value *) }
[@@deriving equal, yojson_of]
(** an error to report to the user *)
type t =
| AccessToInvalidAddress of access_to_invalid_address
| MemoryLeak of {procname: Procname.t; allocation_trace: Trace.t; location: Location.t}
| ReadUninitializedValue of read_uninitialized_value
| StackVariableAddressEscape of {variable: Var.t; history: ValueHistory.t; location: Location.t}
[@@deriving equal]

@ -573,13 +573,9 @@ let check_all_valid callee_proc_name call_location {AbductiveDomain.pre; _} call
| Some callee_access_trace ->
let access_trace = mk_access_trace callee_access_trace in
AddressAttributes.check_initialized access_trace addr_caller astate
|> Result.map_error ~f:(fun invalidation_trace ->
|> Result.map_error ~f:(fun () ->
L.d_printfln "ERROR: caller's %a is uninitialized!" AbstractValue.pp addr_caller ;
( Diagnostic.AccessToInvalidAddress
{ calling_context= []
; invalidation= Uninitialized
; invalidation_trace
; access_trace }
( Diagnostic.ReadUninitializedValue {calling_context= []; trace= access_trace}
, astate ) ) )
call_state.subst (Ok call_state.astate)

@ -50,7 +50,6 @@ type t =
| OptionalEmpty
| StdVector of std_vector_function
| JavaIterator of java_iterator_function
| Uninitialized
[@@deriving compare, equal]
let issue_type_of_cause = function
@ -70,8 +69,6 @@ let issue_type_of_cause = function
IssueType.optional_empty_access
| JavaIterator _ | StdVector _ ->
IssueType.vector_invalidation
| Uninitialized ->
IssueType.uninitialized_value_pulse
let describe f cause =
@ -99,8 +96,6 @@ let describe f cause =
F.fprintf f "was potentially invalidated by `%a()`" pp_std_vector_function std_vector_f
| JavaIterator java_iterator_f ->
F.fprintf f "was potentially invalidated by `%a()`" pp_java_iterator_function java_iterator_f
| Uninitialized ->
F.pp_print_string f "was uninitialized"
let pp f invalidation =
@ -117,5 +112,3 @@ let pp f invalidation =
F.fprintf f "StdVector(%a)" describe invalidation
| JavaIterator _ ->
F.fprintf f "JavaIterator(%a)" describe invalidation
| Uninitialized ->
F.pp_print_string f "Uninitialized"

@ -31,7 +31,6 @@ type t =
| OptionalEmpty
| StdVector of std_vector_function
| JavaIterator of java_iterator_function
| Uninitialized
[@@deriving compare, equal]
val pp : F.formatter -> t -> unit

@ -10,17 +10,23 @@ open PulseBasicInterface
module AbductiveDomain = PulseAbductiveDomain
module Arithmetic = PulseArithmetic
type t = AccessToInvalidAddress of Diagnostic.access_to_invalid_address
type t =
| AccessToInvalidAddress of Diagnostic.access_to_invalid_address
| ReadUninitializedValue of Diagnostic.read_uninitialized_value
[@@deriving equal, yojson_of]
let to_diagnostic = function
| AccessToInvalidAddress access_to_invalid_address ->
Diagnostic.AccessToInvalidAddress access_to_invalid_address
| ReadUninitializedValue read_uninitialized_value ->
Diagnostic.ReadUninitializedValue read_uninitialized_value
let add_call call_and_loc = function
| AccessToInvalidAddress access ->
AccessToInvalidAddress {access with calling_context= call_and_loc :: access.calling_context}
| ReadUninitializedValue read ->
ReadUninitializedValue {read with calling_context= call_and_loc :: read.calling_context}
let should_report (astate : AbductiveDomain.summary) =
@ -37,3 +43,5 @@ let should_report_diagnostic (astate : AbductiveDomain.summary) (diagnostic : Di
`ReportNow
| AccessToInvalidAddress diag ->
if should_report astate then `ReportNow else `DelayReport (AccessToInvalidAddress diag)
| ReadUninitializedValue diag ->
if should_report astate then `ReportNow else `DelayReport (ReadUninitializedValue diag)

@ -13,7 +13,9 @@ module AbductiveDomain = PulseAbductiveDomain
but we want to delay reporting until we see the conditions for the bug manifest themselves in
some calling context. *)
type t = AccessToInvalidAddress of Diagnostic.access_to_invalid_address
type t =
| AccessToInvalidAddress of Diagnostic.access_to_invalid_address
| ReadUninitializedValue of Diagnostic.read_uninitialized_value
[@@deriving equal, yojson_of]
val to_diagnostic : t -> Diagnostic.t

@ -152,7 +152,7 @@ module C = struct
let astate_alloc =
PulseArithmetic.and_positive ret_addr astate
|> PulseOperations.allocate callee_procname location ret_value
|> set_uninitialized size_exp_opt location ret_value
|> set_uninitialized size_exp_opt location ret_addr
in
let+ astate_null =
PulseArithmetic.and_eq_int ret_addr IntLit.zero astate
@ -171,7 +171,7 @@ module C = struct
let astate =
PulseOperations.allocate callee_procname location ret_value astate
|> PulseArithmetic.and_positive ret_addr
|> set_uninitialized size_exp_opt location ret_value
|> set_uninitialized size_exp_opt location ret_addr
in
ok_continue astate

@ -27,17 +27,9 @@ let check_addr_access access_mode location (address, history) astate =
in
match access_mode with
| Read ->
let+ astate =
AddressAttributes.check_initialized access_trace address astate
|> Result.map_error ~f:(fun invalidation_trace ->
( Diagnostic.AccessToInvalidAddress
{ calling_context= []
; invalidation= Uninitialized
; invalidation_trace
; access_trace }
, astate ) )
in
astate
AddressAttributes.check_initialized access_trace address astate
|> Result.map_error ~f:(fun () ->
(Diagnostic.ReadUninitializedValue {calling_context= []; trace= access_trace}, astate) )
| Write ->
Ok (AbductiveDomain.initialize address astate)
| NoAccess ->

@ -3,10 +3,10 @@ codetoanalyze/c/pulse/memory_leak.c, malloc_interproc_no_free_bad2, 4, MEMORY_LE
codetoanalyze/c/pulse/memory_leak.c, malloc_no_free_bad, 0, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/c/pulse/nullptr.c, malloc_no_check_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,allocated by call to `malloc` (modelled),is the null pointer,use-after-lifetime part of the trace starts here,allocated by call to `malloc` (modelled),assigned,invalid access occurs here]
codetoanalyze/c/pulse/nullptr.c, nullptr_deref_young_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, call_to_use_and_mayinit_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, dereference_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `p` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `p` declared here,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_nop_in_callee_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_read_in_callee_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,when calling `read_int_ref` here,parameter `p` of read_int_ref,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_uninit_in_callee_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `uninit` here,allocated by call to `malloc` (modelled),was uninitialized,use-after-lifetime part of the trace starts here,passed as argument to `uninit`,return from call to `uninit`,assigned,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, malloc_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,allocated by call to `malloc` (modelled),was uninitialized,use-after-lifetime part of the trace starts here,allocated by call to `malloc` (modelled),assigned,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, self_assign_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,invalid access occurs here]
codetoanalyze/c/pulse/uninit.c, call_to_use_and_mayinit_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, dereference_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `p` declared here,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_nop_in_callee_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_read_in_callee_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,when calling `read_int_ref` here,parameter `p` of read_int_ref,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, interprocedural_uninit_in_callee_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [passed as argument to `uninit`,return from call to `uninit`,assigned,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, malloc_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [allocated by call to `malloc` (modelled),assigned,read to uninitialized value occurs here]
codetoanalyze/c/pulse/uninit.c, self_assign_bad, 2, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,read to uninitialized value occurs here]

@ -10,7 +10,7 @@ codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_captured_var_leak_bad, 6,
codetoanalyze/objc/pulse/NPEBlocks.m, Singleton.dispatch_once_no_npe_good_FP, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here]
codetoanalyze/objc/pulse/NPEBlocks.m, captured_npe_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,when calling `objc_blockcaptured_npe_bad_3` here,parameter `x` of objc_blockcaptured_npe_bad_3,invalid access occurs here]
codetoanalyze/objc/pulse/NPEBlocks.m, captured_npe_ok_FP, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here]
codetoanalyze/objc/pulse/uninit.m, Uninit.capture_in_closure_bad, 7, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,invalid access occurs here]
codetoanalyze/objc/pulse/uninit.m, Uninit.not_set_in_closure_bad, 7, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [invalidation part of the trace starts here,variable `x` declared here,was uninitialized,use-after-lifetime part of the trace starts here,variable `x` declared here,invalid access occurs here]
codetoanalyze/objc/pulse/uninit.m, Uninit.capture_in_closure_bad, 7, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,read to uninitialized value occurs here]
codetoanalyze/objc/pulse/uninit.m, Uninit.not_set_in_closure_bad, 7, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [variable `x` declared here,read to uninitialized value occurs here]
codetoanalyze/objc/pulse/use_after_free.m, PulseTest.use_after_free_simple_in_objc_method_bad:, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,invalid access occurs here]
codetoanalyze/objc/pulse/use_after_free.m, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of use_after_free_simple_bad,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of use_after_free_simple_bad,invalid access occurs here]

Loading…
Cancel
Save