[AL] Adding predicate for AL rule to check that a variable of a specific type is being captured in a block

Reviewed By: ddino

Differential Revision: D17261362

fbshipit-source-id: 81f2e4bdb
master
Dulma Churchill 5 years ago committed by Facebook Github Bot
parent ab683af1f1
commit 86140581d5

@ -1592,3 +1592,20 @@ let is_in_source_file an path_re =
let is_referencing_decl_from_source_file an path_re =
source_file_matches (Ctl_parser_types.get_referenced_decl_source_file an) path_re
let captured_var_of_type typ captured_var =
match captured_var.Clang_ast_t.bcv_variable with
| Some dr ->
let _, _, qt = CAst_utils.get_info_from_decl_ref dr in
type_ptr_equal_type qt.Clang_ast_t.qt_type_ptr (ALVar.alexp_to_string typ)
| _ ->
false
let objc_block_is_capturing_var_of_type an typ =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.BlockDecl (_, bdi)) ->
List.exists ~f:(captured_var_of_type typ) bdi.bdi_captured_variables
| _ ->
false

@ -14,6 +14,9 @@ type t = ALVar.formula_id * ALVar.alexp list [@@deriving compare]
val captured_variables_cxx_ref : Ctl_parser_types.ast_node -> Clang_ast_t.named_decl_info list
(** list of cxx references captured by an ObjC Block *)
val objc_block_is_capturing_var_of_type : Ctl_parser_types.ast_node -> ALVar.t -> bool
(** true if the ObjC Block captures a variable of a given type *)
val objc_block_is_capturing_values : Ctl_parser_types.ast_node -> bool
(** true if the ObjC Block captures any variables *)

@ -1222,6 +1222,8 @@ let rec eval_Atomic pred_name_ args an lcxt =
CPredicates.is_in_source_file an path_re
| "is_referencing_decl_from_source_file", [path_re], an ->
CPredicates.is_referencing_decl_from_source_file an path_re
| "objc_block_is_capturing_var_of_type", [typ], an ->
CPredicates.objc_block_is_capturing_var_of_type an typ
| _ ->
L.(die ExternalError) "Undefined Predicate or wrong set of arguments: '%s'" pred_name

@ -877,3 +877,14 @@ DEFINE-CHECKER TEST_IS_OPTIONAL_METHOD = {
SET message = "This is an optional method";
};
DEFINE-CHECKER IVAR_CAPTURED_IN_OBJC_BLOCK = {
SET report_when =
WHEN
objc_block_is_capturing_var_of_type("Ivars*")
HOLDS-IN-NODE BlockDecl;
SET message = "Found ivar of a given type captured in block";
SET severity = "ERROR";
SET mode = "ON";
};

@ -329,6 +329,7 @@ codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_
codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_IS_OVERRIDING_METHOD, no_bucket, WARNING, []
codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_UNAVAILABLE_ATTR, no_bucket, WARNING, []
codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::newWithFoo, 13, TEST_INSTANCE_TYPE, no_bucket, WARNING, []
codetoanalyze/objc/linters-for-test-only/variables_captured_in_block.m, objc_block, 26, IVAR_CAPTURED_IN_OBJC_BLOCK, no_bucket, ERROR, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 29, TEST_DEFAULT_VISIBILITY, no_bucket, WARNING, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 30, TEST_DEFAULT_VISIBILITY, no_bucket, WARNING, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 31, TEST_HIDDEN_VISIBILITY, no_bucket, WARNING, []

@ -0,0 +1,30 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/NSObject.h>
typedef struct LSIvarsContext {
void* ivars;
} LSIvarsContext;
typedef struct Ivars {
void (*dealloc)(struct Ivars*);
NSString* str;
} Ivars;
@interface T : NSObject
@end
@implementation T
- (void)m {
LSIvarsContext __blablaContext;
Ivars* blabla = (Ivars*)__blablaContext.ivars;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
blabla->str = @"str";
});
}
@end
Loading…
Cancel
Save