From b8298f163f15b7ec1e2c6e302e6506f328a1c94f Mon Sep 17 00:00:00 2001 From: Dulma Churchill Date: Tue, 19 Nov 2024 06:48:36 -0800 Subject: [PATCH] [self-in-block] Do not report strongSelf Not Checked when passed to a nullable position Summary: Sometimes it's needed to do those calls even if `strongSelf` is nil. Reviewed By: ngorogiannis Differential Revision: D66109087 Privacy Context Container: L1208441 fbshipit-source-id: 11129312a0a088c3874ac7d65287cacdda5501b4 --- infer/src/checkers/SelfInBlock.ml | 31 +++++++++++++++++-- .../objc/self-in-block/StrongSelf.m | 2 +- .../objc/self-in-block/issues.exp | 1 - 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/infer/src/checkers/SelfInBlock.ml b/infer/src/checkers/SelfInBlock.ml index 291348ce55..09c998dd3b 100644 --- a/infer/src/checkers/SelfInBlock.ml +++ b/infer/src/checkers/SelfInBlock.ml @@ -372,6 +372,26 @@ module TransferFunctions = struct false + let clear_unchecked_use_args attributes args (astate : Domain.t) = + let clear_unchecked_use_non_nullable_arg astate (arg, _) annotation = + match arg with + | Exp.Var id when Annotations.ia_is_nullable annotation -> + Domain.clear_unchecked_use id astate + | _ -> + astate + in + let args = + if is_objc_instance (Some attributes) then match args with _ :: rest -> rest | [] -> [] + else args + in + let annotations = List.map attributes.ProcAttributes.formals ~f:trd3 in + match List.fold2 ~f:clear_unchecked_use_non_nullable_arg ~init:astate args annotations with + | List.Or_unequal_lengths.Ok astate -> + astate + | List.Or_unequal_lengths.Unequal_lengths -> + astate + + let exec_instr (astate : Domain.t) {IntraproceduralAnalysis.proc_desc} _cfg_node _ (instr : Sil.instr) = let attributes = Procdesc.get_attributes proc_desc in @@ -400,11 +420,11 @@ module TransferFunctions = struct when Exp.is_null_literal e (* if !(strongSef != nil) *) -> Domain.clear_unchecked_use id astate | Call (_, Exp.Const (Const.Cfun callee_pn), args, _, cf) -> + let attributes_opt = Attributes.load callee_pn in let fst = if cf.CallFlags.cf_virtual then List.hd args - else - let attributes_opt = Attributes.load callee_pn in - if is_objc_instance attributes_opt then List.hd args else None + else if is_objc_instance attributes_opt then List.hd args + else None in let astate = Option.value_map @@ -412,6 +432,11 @@ module TransferFunctions = struct match arg with Exp.Var id -> Domain.clear_unchecked_use id astate | _ -> astate ) ~default:astate fst in + let astate = + Option.value_map + ~f:(fun attributes -> clear_unchecked_use_args attributes args astate) + attributes_opt ~default:astate + in List.fold ~init:astate ~f:(fun astate (exp, _) -> Domain.process_exp exp astate) args | _ -> astate diff --git a/infer/tests/codetoanalyze/objc/self-in-block/StrongSelf.m b/infer/tests/codetoanalyze/objc/self-in-block/StrongSelf.m index 74b6e9de62..763cdb40f8 100644 --- a/infer/tests/codetoanalyze/objc/self-in-block/StrongSelf.m +++ b/infer/tests/codetoanalyze/objc/self-in-block/StrongSelf.m @@ -131,7 +131,7 @@ - (void)strongSelfCheck2_bad { }; } -- (void)strongSelfCheck6_bad { +- (void)strongSelfCheck6_good { __weak __typeof(self) weakSelf = self; int (^my_block)(BOOL) = ^(BOOL isTapped) { __strong __typeof(weakSelf) strongSelf = weakSelf; diff --git a/infer/tests/codetoanalyze/objc/self-in-block/issues.exp b/infer/tests/codetoanalyze/objc/self-in-block/issues.exp index ede82e7cfb..941bf81bf5 100644 --- a/infer/tests/codetoanalyze/objc/self-in-block/issues.exp +++ b/infer/tests/codetoanalyze/objc/self-in-block/issues.exp @@ -12,7 +12,6 @@ codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:78, 1, CA codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:97, 2, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf] codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:106, 6, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf,Using &strongSelf,Using &strongSelf,Using &strongSelf], +""=>"\n if (!strongSelf) { return; }"@112:1 codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:121, 6, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf,Using &strongSelf,Using &strongSelf] -codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:136, 2, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf] codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:158, 2, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf,Using &strongSelf] codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:170, 2, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf,Using &strongSelf] codetoanalyze/objc/self-in-block/StrongSelf.m, objc_block_StrongSelf.m:179, 3, STRONG_SELF_NOT_CHECKED, no_bucket, ERROR, [Using &strongSelf,Using &strongSelf]