diff --git a/infer/src/pulse/Pulse.ml b/infer/src/pulse/Pulse.ml index afb52b4c7..3c78726e8 100644 --- a/infer/src/pulse/Pulse.ml +++ b/infer/src/pulse/Pulse.ml @@ -42,6 +42,8 @@ module PulseTransferFunctions = struct PulseCallOperations.call tenv ~caller_proc_desc:proc_desc ~callee_data call_loc callee_pname ~ret ~actuals ~formals_opt astate | _ -> + (* dereference call expression to catch nil issues *) + let<*> astate, _ = PulseOperations.eval_deref call_loc call_exp astate in L.d_printfln "Skipping indirect call %a@\n" Exp.pp call_exp ; let astate = let arg_values = List.map actuals ~f:(fun ((value, _), _) -> value) in diff --git a/infer/tests/codetoanalyze/objc/pulse/NPENilBlocks.m b/infer/tests/codetoanalyze/objc/pulse/NPENilBlocks.m index 8368d441c..8ea9fdfeb 100644 --- a/infer/tests/codetoanalyze/objc/pulse/NPENilBlocks.m +++ b/infer/tests/codetoanalyze/objc/pulse/NPENilBlocks.m @@ -20,7 +20,7 @@ my_block(); } -- (void)FN_assignNilBad { +- (void)assignNilBad { void (^my_block)(void) = ^() { }; @@ -35,13 +35,13 @@ } } -- (void)FN_paramAssignNilBad:(void (^)(void))my_block { +- (void)paramAssignNilBad:(void (^)(void))my_block { my_block = NULL; my_block(); // Null deref } -- (void)FN_paramReassignNilBad:(void (^)(void))my_block_param { +- (void)paramReassignNilBad:(void (^)(void))my_block_param { void (^my_block)(void) = ^() { }; @@ -95,7 +95,7 @@ void calldoSomethingThenCallbackOk() { [blockA doSomethingThenCallback:my_block]; } -void FN_calldoSomethingThenCallbackWithNilBad() { +void calldoSomethingThenCallbackWithNilBad() { BlockA* blockA = [BlockA alloc]; [blockA doSomethingThenCallback:nil]; } diff --git a/infer/tests/codetoanalyze/objc/pulse/issues.exp b/infer/tests/codetoanalyze/objc/pulse/issues.exp index 5b4fd0b1c..ca22b8d69 100644 --- a/infer/tests/codetoanalyze/objc/pulse/issues.exp +++ b/infer/tests/codetoanalyze/objc/pulse/issues.exp @@ -9,6 +9,10 @@ codetoanalyze/objc/pulse/MemoryLeaks.m, call_cfrelease_interproc_leak_ok_FP, 3, codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_captured_var_leak_bad, 7, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc_no_fail` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/NPEBlocks.m, Singleton.dispatch_once_no_npe_good_FP, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/objc/pulse/NPEBlocks.m, captured_npe_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,when calling `objc_blockcaptured_npe_bad_3` here,parameter `x` of objc_blockcaptured_npe_bad_3,invalid access occurs here] +codetoanalyze/objc/pulse/NPENilBlocks.m, BlockA.assignNilBad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] +codetoanalyze/objc/pulse/NPENilBlocks.m, BlockA.paramAssignNilBad:, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] +codetoanalyze/objc/pulse/NPENilBlocks.m, BlockA.paramReassignNilBad:, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,assigned,invalid access occurs here] +codetoanalyze/objc/pulse/NPENilBlocks.m, calldoSomethingThenCallbackWithNilBad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,when calling `BlockA.doSomethingThenCallback:` here,parameter `my_block` of BlockA.doSomethingThenCallback:,invalid access occurs here] codetoanalyze/objc/pulse/uninit.m, Uninit.call_setter_c_struct_bad, 3, PULSE_UNINITIALIZED_VALUE, no_bucket, ERROR, [struct field address `x` created,when calling `Uninit.setS:` here,parameter `s` of Uninit.setS:,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]