From 9980c4f61471b07568718e0b769183e49e1fa066 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Wed, 12 May 2021 02:43:58 -0700 Subject: [PATCH] [pulse] correct order of calling context in trace Summary: The order was reversed when printing the trace, leading to confusion. Also make sure we indicate which part of the trace we are printing when there is more than one part (either context + access or invalidation + access, or all three). Also start nesting at to better represent the role of the calling context visually. Reviewed By: da319 Differential Revision: D28329263 fbshipit-source-id: b691fb1f4 --- infer/src/pulse/PulseDiagnostic.ml | 87 +++++++++++-------- infer/src/pulse/PulseDiagnostic.mli | 5 +- .../codetoanalyze/c/pulse/interprocedural.c | 18 ++++ infer/tests/codetoanalyze/c/pulse/issues.exp | 6 +- .../codetoanalyze/c/pulse/issues.exp-isl | 6 +- .../tests/codetoanalyze/java/pulse/issues.exp | 2 +- .../codetoanalyze/java/pulse/issues.exp-isl | 2 +- .../codetoanalyze/objcpp/pulse/issues.exp | 2 +- 8 files changed, 84 insertions(+), 44 deletions(-) diff --git a/infer/src/pulse/PulseDiagnostic.ml b/infer/src/pulse/PulseDiagnostic.ml index 36b443b2c..925fd7b0c 100644 --- a/infer/src/pulse/PulseDiagnostic.ml +++ b/infer/src/pulse/PulseDiagnostic.ml @@ -209,10 +209,9 @@ let get_message diagnostic = pulse_start_msg pp_var variable -let add_errlog_header ~title location errlog = - let depth = 0 in +let add_errlog_header ~nesting ~title location errlog = let tags = [] in - Errlog.make_trace_element depth location title tags :: errlog + Errlog.make_trace_element nesting location title tags :: errlog let get_trace_calling_context calling_context errlog = @@ -220,57 +219,75 @@ let get_trace_calling_context calling_context errlog = | [] -> 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) -> + add_errlog_header ~nesting:0 ~title:"calling context starts here" first_call_loc + @@ ( (* errlog is built in the reverse order so reverse everything first *) + List.fold (List.rev calling_context) + ~init:(errlog, List.length calling_context - 1) + ~f:(fun (errlog, depth) (call, loc) -> ( Errlog.make_trace_element depth loc (F.asprintf "in call to %a" CallEvent.pp call) [] :: errlog - , depth + 1 ) ) + , depth - 1 ) ) |> fst ) -let add_invalidation_trace (invalidation : Invalidation.t) invalidation_trace access_trace errlog = - let start_title, access_title = - match invalidation with - | ConstantDereference i when IntLit.equal i IntLit.zero -> - ( "source of the null value part of the trace starts here" - , "null pointer dereference part of the trace starts here" ) - | ConstantDereference _ -> - ( "source of the constant value part of the trace starts here" - , "constant value dereference part of the trace starts here" ) - | CFree - | CppDelete - | EndIterator - | GoneOutOfScope _ - | OptionalEmpty - | StdVector _ - | JavaIterator _ -> - ( "invalidation part of the trace starts here" - , "use-after-lifetime part of the trace starts here" ) - in +let invalidation_titles (invalidation : Invalidation.t) = + match invalidation with + | ConstantDereference i when IntLit.equal i IntLit.zero -> + ( "source of the null value part of the trace starts here" + , "null pointer dereference part of the trace starts here" ) + | ConstantDereference _ -> + ( "source of the constant value part of the trace starts here" + , "constant value dereference part of the trace starts here" ) + | CFree + | CppDelete + | EndIterator + | GoneOutOfScope _ + | OptionalEmpty + | StdVector _ + | JavaIterator _ -> + ( "invalidation part of the trace starts here" + , "use-after-lifetime part of the trace starts here" ) + + +let add_invalidation_trace ~nesting invalidation invalidation_trace errlog = + let start_title = invalidation_titles invalidation |> fst in let start_location = Trace.get_start_location invalidation_trace in - add_errlog_header ~title:start_title start_location - @@ Trace.add_to_errlog ~nesting:1 + add_errlog_header ~nesting ~title:start_title start_location + @@ Trace.add_to_errlog ~nesting:(nesting + 1) ~pp_immediate:(fun fmt -> F.fprintf fmt "%a" Invalidation.describe invalidation) invalidation_trace - @@ + @@ errlog + + +let add_access_trace ~include_title ~nesting invalidation access_trace errlog = let access_start_location = Trace.get_start_location access_trace in - add_errlog_header ~title:access_title access_start_location @@ errlog + let access_title = invalidation_titles invalidation |> snd in + ( if include_title then add_errlog_header ~nesting ~title:access_title access_start_location + else Fn.id ) + @@ Trace.add_to_errlog ~nesting:(nesting + 1) + ~pp_immediate:(fun fmt -> F.pp_print_string fmt "invalid access occurs here") + access_trace + @@ errlog let get_trace = function | AccessToInvalidAddress {calling_context; invalidation; invalidation_trace; access_trace} -> + let in_context_nesting = List.length calling_context in + let should_print_invalidation_trace = not (trace_contains_invalidation access_trace) in get_trace_calling_context calling_context - @@ ( if trace_contains_invalidation access_trace then Fn.id - else add_invalidation_trace invalidation invalidation_trace access_trace ) - @@ Trace.add_to_errlog ~nesting:1 - ~pp_immediate:(fun fmt -> F.pp_print_string fmt "invalid access occurs here") - access_trace + @@ ( if should_print_invalidation_trace then + add_invalidation_trace ~nesting:in_context_nesting invalidation invalidation_trace + else Fn.id ) + @@ add_access_trace + ~include_title:(should_print_invalidation_trace || not (List.is_empty calling_context)) + ~nesting:in_context_nesting invalidation access_trace @@ [] | MemoryLeak {location; allocation_trace} -> let access_start_location = Trace.get_start_location allocation_trace in - add_errlog_header ~title:"allocation part of the trace starts here" access_start_location + add_errlog_header ~nesting:0 ~title:"allocation part of the trace starts here" + access_start_location @@ Trace.add_to_errlog ~nesting:1 ~pp_immediate:(fun fmt -> F.pp_print_string fmt "allocation part of the trace ends here") allocation_trace diff --git a/infer/src/pulse/PulseDiagnostic.mli b/infer/src/pulse/PulseDiagnostic.mli index 86e4146ed..f624b575e 100644 --- a/infer/src/pulse/PulseDiagnostic.mli +++ b/infer/src/pulse/PulseDiagnostic.mli @@ -13,8 +13,9 @@ module ValueHistory = PulseValueHistory type access_to_invalid_address = { 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 *) + (** the list of function calls leading to the issue being realised, in + outermost-to-innermost order, which is an additional common prefix to the traces in the + record *) ; invalidation: Invalidation.t ; invalidation_trace: Trace.t (** assuming we are in the calling context, the trace leads to [invalidation] without diff --git a/infer/tests/codetoanalyze/c/pulse/interprocedural.c b/infer/tests/codetoanalyze/c/pulse/interprocedural.c index 0c40c84ce..0882c2d74 100644 --- a/infer/tests/codetoanalyze/c/pulse/interprocedural.c +++ b/infer/tests/codetoanalyze/c/pulse/interprocedural.c @@ -30,3 +30,21 @@ void test_modified_value_then_error_bad(int* x) { *p = 42; } } + +// below is a test that the calling context appears in the correct order in the +// trace + +void latent(int a) { + if (a == 4) { + int* p = NULL; + *p = 42; + } +} + +void propagate_latent_1_latent(int a1) { latent(a1); } + +void propagate_latent_2_latent(int a2) { propagate_latent_1_latent(a2); } + +void propagate_latent_3_latent(int a3) { propagate_latent_2_latent(a3); } + +void make_latent_manifest() { propagate_latent_3_latent(4); } diff --git a/infer/tests/codetoanalyze/c/pulse/issues.exp b/infer/tests/codetoanalyze/c/pulse/issues.exp index d8075f9fc..515ba771a 100644 --- a/infer/tests/codetoanalyze/c/pulse/issues.exp +++ b/infer/tests/codetoanalyze/c/pulse/issues.exp @@ -1,8 +1,10 @@ codetoanalyze/c/pulse/frontend.c, assign_implicit_cast_bad, 8, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/frontend.c, assign_paren_bad, 8, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] -codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid2_bad, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `call_if_freed_invalid_latent`,is the null pointer,when calling `if_freed_invalid_latent` here,parameter `y` of if_freed_invalid_latent,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid2_bad, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `call_if_freed_invalid_latent`,null pointer dereference part of the trace starts here,is the null pointer,when calling `if_freed_invalid_latent` here,parameter `y` of if_freed_invalid_latent,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid_latent, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,when calling `if_freed_invalid_latent` here,parameter `y` of if_freed_invalid_latent,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, if_freed_invalid_latent, 3, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `y` of if_freed_invalid_latent,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `y` of if_freed_invalid_latent,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, latent, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, make_latent_manifest, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `propagate_latent_3_latent`,in call to `propagate_latent_2_latent`,in call to `propagate_latent_1_latent`,in call to `latent`,null pointer dereference part of the trace starts here,is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, test_modified_value_then_error_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/latent.c, FN_nonlatent_use_after_free_bad, 6, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `x` of FN_nonlatent_use_after_free_bad,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of FN_nonlatent_use_after_free_bad,invalid access occurs here] codetoanalyze/c/pulse/latent.c, latent_use_after_free, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,source of the null value part of the trace starts here,is the null pointer,null pointer dereference part of the trace starts here,parameter `x` of latent_use_after_free,invalid access occurs here] @@ -28,7 +30,7 @@ codetoanalyze/c/pulse/nullptr.c, null_alias_bad, 4, MEMORY_LEAK, no_bucket, ERRO codetoanalyze/c/pulse/nullptr.c, nullptr_deref_young_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, access_null_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, access_use_after_free_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `l` of access_use_after_free_bad,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `l` of access_use_after_free_bad,invalid access occurs here] -codetoanalyze/c/pulse/traces.c, call_makes_null_deref_manifest_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `something_about_strings_latent`,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] +codetoanalyze/c/pulse/traces.c, call_makes_null_deref_manifest_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `something_about_strings_latent`,null pointer dereference part of the trace starts here,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, simple_deref, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, simple_deref_via_alias, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, something_about_strings_latent, 12, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/c/pulse/issues.exp-isl b/infer/tests/codetoanalyze/c/pulse/issues.exp-isl index f216c2c09..0919aedbd 100644 --- a/infer/tests/codetoanalyze/c/pulse/issues.exp-isl +++ b/infer/tests/codetoanalyze/c/pulse/issues.exp-isl @@ -1,8 +1,10 @@ codetoanalyze/c/pulse/frontend.c, assign_implicit_cast_bad, 8, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/frontend.c, assign_paren_bad, 8, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] -codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid2_bad, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `call_if_freed_invalid_latent`,is the null pointer,when calling `if_freed_invalid_latent` here,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid2_bad, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `call_if_freed_invalid_latent`,null pointer dereference part of the trace starts here,is the null pointer,when calling `if_freed_invalid_latent` here,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, call_if_freed_invalid_latent, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,when calling `if_freed_invalid_latent` here,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, if_freed_invalid_latent, 3, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, latent, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/c/pulse/interprocedural.c, make_latent_manifest, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `propagate_latent_3_latent`,in call to `propagate_latent_2_latent`,in call to `propagate_latent_1_latent`,in call to `latent`,null pointer dereference part of the trace starts here,is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/interprocedural.c, test_modified_value_then_error_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/latent.c, FN_nonlatent_use_after_free_bad, 6, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,invalid access occurs here] codetoanalyze/c/pulse/latent.c, latent_use_after_free, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,source of the null value part of the trace starts here,is the null pointer,null pointer dereference part of the trace starts here,invalid access occurs here] @@ -27,7 +29,7 @@ codetoanalyze/c/pulse/nullptr.c, null_alias_bad, 4, MEMORY_LEAK, no_bucket, ERRO codetoanalyze/c/pulse/nullptr.c, nullptr_deref_young_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, access_null_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, access_use_after_free_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,invalid access occurs here] -codetoanalyze/c/pulse/traces.c, call_makes_null_deref_manifest_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `something_about_strings_latent`,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] +codetoanalyze/c/pulse/traces.c, call_makes_null_deref_manifest_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `something_about_strings_latent`,null pointer dereference part of the trace starts here,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, simple_deref, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, simple_deref_via_alias, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,assigned,invalid access occurs here] codetoanalyze/c/pulse/traces.c, something_about_strings_latent, 12, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,allocated by call to `malloc` (modelled),is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/java/pulse/issues.exp b/infer/tests/codetoanalyze/java/pulse/issues.exp index 27e4aa30b..c9857ab3f 100644 --- a/infer/tests/codetoanalyze/java/pulse/issues.exp +++ b/infer/tests/codetoanalyze/java/pulse/issues.exp @@ -18,7 +18,7 @@ codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapEx codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getAfterRemovingTheKeyBad():void, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [passed as argument to `Map.get()` (modelled),return from call to `Map.get()` (modelled),is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getOneIntegerWithoutCheckBad():int, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [passed as argument to `Map.get()` (modelled),return from call to `Map.get()` (modelled),is the null pointer,assigned,passed as argument to `cast` (modelled),return from call to `cast` (modelled),assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.checkInstanceArray(java.lang.Object):void, 7, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] -codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfBooleanArrayBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `void InstanceOfExample.checkInstanceArray(Object)`,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfBooleanArrayBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `void InstanceOfExample.checkInstanceArray(Object)`,null pointer dereference part of the trace starts here,is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfNullIntraBad():void, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfObjProfessorBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [source of the null value part of the trace starts here,when calling `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)` here,assigned,is the null pointer,null pointer dereference part of the trace starts here,passed as argument to `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)`,return from call to `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)`,assigned,invalid access occurs here] codetoanalyze/java/pulse/IntegerExample.java, codetoanalyze.java.infer.IntegerExample.FP_testIntegerBuiltInEqualOperatorCachedValuesOk():void, 19, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/java/pulse/issues.exp-isl b/infer/tests/codetoanalyze/java/pulse/issues.exp-isl index 0d1ec1bea..46a9b4f81 100644 --- a/infer/tests/codetoanalyze/java/pulse/issues.exp-isl +++ b/infer/tests/codetoanalyze/java/pulse/issues.exp-isl @@ -17,7 +17,7 @@ codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapEx codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getAfterRemovingTheKeyBad():void, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [passed as argument to `Map.get()` (modelled),return from call to `Map.get()` (modelled),is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getOneIntegerWithoutCheckBad():int, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [passed as argument to `Map.get()` (modelled),return from call to `Map.get()` (modelled),is the null pointer,assigned,passed as argument to `cast` (modelled),return from call to `cast` (modelled),assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.checkInstanceArray(java.lang.Object):void, 7, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] -codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfBooleanArrayBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `void InstanceOfExample.checkInstanceArray(Object)`,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfBooleanArrayBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [calling context starts here,in call to `void InstanceOfExample.checkInstanceArray(Object)`,null pointer dereference part of the trace starts here,is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfNullIntraBad():void, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/java/pulse/InstanceOfExample.java, InstanceOfExample.testInstanceOfObjProfessorBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [source of the null value part of the trace starts here,when calling `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)` here,assigned,is the null pointer,null pointer dereference part of the trace starts here,passed as argument to `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)`,return from call to `InstanceOfExample$Person InstanceOfExample.updatePerson(InstanceOfExample$Person)`,assigned,invalid access occurs here] codetoanalyze/java/pulse/IntegerExample.java, codetoanalyze.java.infer.IntegerExample.FP_testIntegerBuiltInEqualOperatorCachedValuesOk():void, 19, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp index 12e913773..3a6889ef2 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp @@ -12,7 +12,7 @@ codetoanalyze/objcpp/pulse/NPEBasic.mm, replaceNilInArrayBad, 1, NIL_INSERTION_I codetoanalyze/objcpp/pulse/NPEBasic.mm, testAccessPropertyAccessorBad, 2, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [is the null pointer,assigned,when calling `SomeObject.ptr` here,parameter `self` of SomeObject.ptr,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODBad, 2, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODLatent, 7, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here] -codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODLatentBad, 1, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [calling context starts here,in call to `testCallMethodReturnsnonPODLatent`,is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here] +codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODLatentBad, 1, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [calling context starts here,in call to `testCallMethodReturnsnonPODLatent`,null pointer dereference part of the trace starts here,is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testNilMessagingForModelNilNilOK_FP, 0, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `addObjectInDict` here,parameter `value` of addObjectInDict,passed as argument to `NSMutableDictionary.setObject:forKey:` (modelled),return from call to `NSMutableDictionary.setObject:forKey:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testNilMessagingForModelNotNilDictBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `addObjectInDict` here,parameter `value` of addObjectInDict,passed as argument to `NSMutableDictionary.setObject:forKey:` (modelled),return from call to `NSMutableDictionary.setObject:forKey:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testNonPODTraceBad, 2, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [source of the null value part of the trace starts here,when calling `SomeObject.returnsNil` here,assigned,is the null pointer,null pointer dereference part of the trace starts here,passed as argument to `SomeObject.returnsNil`,return from call to `SomeObject.returnsNil`,passed as argument to `SomeObject.get`,return from call to `SomeObject.get`,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here]