From da2717ff2a851a99c348852a591873283e4b6af5 Mon Sep 17 00:00:00 2001 From: Martino Luca Date: Thu, 28 Jul 2016 05:22:47 -0700 Subject: [PATCH] Migrate BAD_POINTER_COMPARISON check from backend to linters infra Reviewed By: dulmarod Differential Revision: D3614726 fbshipit-source-id: bdc7651 --- infer/src/backend/errdesc.ml | 7 +--- infer/src/backend/errdesc.mli | 3 -- infer/src/backend/exceptions.ml | 5 --- infer/src/backend/exceptions.mli | 1 - infer/src/backend/localise.ml | 12 ------ infer/src/backend/localise.mli | 1 - infer/src/backend/symExec.ml | 25 ----------- infer/src/clang/cFrontend_checkers.ml | 38 +++++++++++++++++ infer/src/clang/cFrontend_checkers.mli | 3 ++ infer/src/clang/cFrontend_checkers_main.ml | 2 +- infer/src/clang/cFrontend_errors.ml | 42 +++++++++++++++++++ infer/src/clang/cFrontend_utils.ml | 12 ++++++ infer/src/clang/cFrontend_utils.mli | 2 + infer/src/clang/cIssue.ml | 3 ++ infer/src/clang/cIssue.mli | 1 + .../badpointer.m | 0 .../nsnumber.m | 38 +++++++++++++++-- .../{infer => linters}/NSNumber2Test.java | 18 ++------ .../objc/{infer => linters}/NSNumberTest.java | 16 ++----- infer/tests/utils/InferResults.java | 1 + 20 files changed, 146 insertions(+), 84 deletions(-) rename infer/tests/codetoanalyze/objc/{errors/bad_ptr_comparisons => linters}/badpointer.m (100%) rename infer/tests/codetoanalyze/objc/{errors/bad_ptr_comparisons => linters}/nsnumber.m (56%) rename infer/tests/endtoend/objc/{infer => linters}/NSNumber2Test.java (79%) rename infer/tests/endtoend/objc/{infer => linters}/NSNumberTest.java (80%) diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index a94b9de9f..cf4853b58 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -440,11 +440,6 @@ let explain_allocation_mismatch ra_alloc ra_dealloc = Localise.desc_allocation_mismatch (get_primitive_called true ra_alloc) (get_primitive_called false ra_dealloc) -(** Produce a description of a pointer dangerously coerced to a boolean in a comparison *) -let explain_bad_pointer_comparison exp node loc = - let dexp_opt = exp_rv_dexp node exp in - Localise.desc_bad_pointer_comparison dexp_opt loc - (** check whether the type of leaked [hpred] appears as a predicate in an inductive predicate in [prop] *) let leak_from_list_abstraction hpred prop = @@ -517,7 +512,7 @@ let explain_leak tenv hpred prop alloc_att_opt bucket = | _ -> (None, None, None) in let is_file = match resource_opt with | Some Sil.Rfile -> true - | _ -> false in + | _ -> false in let check_pvar pvar = (* check that pvar is local or global and has the same type as the leaked hpred *) (Pvar.is_local pvar || Pvar.is_global pvar) && diff --git a/infer/src/backend/errdesc.mli b/infer/src/backend/errdesc.mli index ea1c4eeeb..af1655301 100644 --- a/infer/src/backend/errdesc.mli +++ b/infer/src/backend/errdesc.mli @@ -44,9 +44,6 @@ val exp_rv_dexp : Cfg.Node.t -> Sil.exp -> DecompiledExp.t option val explain_context_leak : Procname.t -> Typ.t -> Ident.fieldname -> (Ident.fieldname option * Typ.t) list -> Localise.error_desc -(** Produce a description of a pointer dangerously coerced to a boolean in a comparison *) -val explain_bad_pointer_comparison : Sil.exp -> Cfg.Node.t -> Location.t -> Localise.error_desc - (** Produce a description of a mismatch between an allocation function and a deallocation function *) val explain_allocation_mismatch : Sil.res_action -> Sil.res_action -> Localise.error_desc diff --git a/infer/src/backend/exceptions.ml b/infer/src/backend/exceptions.ml index 577ac7cce..9801df994 100644 --- a/infer/src/backend/exceptions.ml +++ b/infer/src/backend/exceptions.ml @@ -37,7 +37,6 @@ exception Array_out_of_bounds_l2 of Localise.error_desc * L.ml_loc exception Array_out_of_bounds_l3 of Localise.error_desc * L.ml_loc exception Array_of_pointsto of L.ml_loc exception Bad_footprint of L.ml_loc -exception Bad_pointer_comparison of Localise.error_desc * L.ml_loc exception Class_cast_exception of Localise.error_desc * L.ml_loc exception Codequery of Localise.error_desc exception Comparing_floats_for_equality of Localise.error_desc * L.ml_loc @@ -121,9 +120,6 @@ let recognize_exception exn = let ml_loc = (f, l, c, c) in (Localise.from_string "Assert_failure", Localise.no_desc, Some ml_loc, Exn_developer, High, None, Nocat) - | Bad_pointer_comparison (desc, ml_loc) -> - (Localise.bad_pointer_comparison, - desc, Some ml_loc, Exn_user, High, Some Kerror, Prover) | Bad_footprint ml_loc -> (Localise.from_string "Bad_footprint", Localise.no_desc, Some ml_loc, Exn_developer, Low, None, Nocat) @@ -351,4 +347,3 @@ let pp_err (_, node_key) loc ekind ex_name desc ml_loc_opt fmt () = let handle_exception exn = let _, _, _, visibility, _, _, _ = recognize_exception exn in visibility == Exn_user || visibility == Exn_developer - diff --git a/infer/src/backend/exceptions.mli b/infer/src/backend/exceptions.mli index dbc7fde0f..7fc027899 100644 --- a/infer/src/backend/exceptions.mli +++ b/infer/src/backend/exceptions.mli @@ -36,7 +36,6 @@ exception Array_out_of_bounds_l1 of Localise.error_desc * Logging.ml_loc exception Array_out_of_bounds_l2 of Localise.error_desc * Logging.ml_loc exception Array_out_of_bounds_l3 of Localise.error_desc * Logging.ml_loc exception Bad_footprint of Logging.ml_loc -exception Bad_pointer_comparison of Localise.error_desc * Logging.ml_loc exception Class_cast_exception of Localise.error_desc * Logging.ml_loc exception Codequery of Localise.error_desc exception Comparing_floats_for_equality of Localise.error_desc * Logging.ml_loc diff --git a/infer/src/backend/localise.ml b/infer/src/backend/localise.ml index d59089a2a..ffbc629fc 100644 --- a/infer/src/backend/localise.ml +++ b/infer/src/backend/localise.ml @@ -475,18 +475,6 @@ let desc_fragment_retains_view fragment_typ fieldname fld_typ pname : error_desc let desc_custom_error loc : error_desc = { no_desc with descriptions = ["detected"; at_line (Tags.create ()) loc] } -let desc_bad_pointer_comparison dexp_opt loc : error_desc = - let dexp_str = match dexp_opt with - | Some dexp -> (DecompiledExp.to_string dexp) ^ " " - | None -> "" in - let line_info = at_line (Tags.create ()) loc in - let check_msg = - "Implicitly checking whether NSNumber pointer " ^ dexp_str ^ "is nil " ^ line_info ^ "." in - let concern_msg = "Did you mean to compare against the unboxed value instead?" in - let fix_msg_rec1 = "Please either explicitly compare " ^ dexp_str ^ "to nil" in - let fix_msg_rec2 = "or use one of the NSNumber accessors before the comparison." in - { no_desc with descriptions = [check_msg; concern_msg; fix_msg_rec1; fix_msg_rec2] } - (** type of access *) type access = | Last_assigned of int * bool (* line, null_case_flag *) diff --git a/infer/src/backend/localise.mli b/infer/src/backend/localise.mli index f15f84df9..c0cbe586e 100644 --- a/infer/src/backend/localise.mli +++ b/infer/src/backend/localise.mli @@ -230,7 +230,6 @@ val desc_fragment_retains_view : (* Create human-readable error description for assertion failures *) val desc_custom_error : Location.t -> error_desc -val desc_bad_pointer_comparison : DecompiledExp.t option -> Location.t -> error_desc (** kind of precondition not met *) type pnm_kind = | Pnm_bounds diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index 0daa3344b..c0febe0a2 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -1058,11 +1058,6 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path true (* skip subpart of a condition obtained from compilation of && and || *) | _ -> false in true_branch && not skip_loop in - (* in comparisons, nil is translated as (void * ) 0 rather than 0 *) - let is_comparison_to_nil = function - | Sil.Cast ((Typ.Tptr (Typ.Tvoid, _)), exp) -> - !Config.curr_language = Config.Clang && Sil.exp_is_zero exp - | _ -> false in match Prop.exp_normalize_prop Prop.prop_emp cond with | Sil.Const (Const.Cint i) when report_condition_always_true_false i -> let node = State.get_node () in @@ -1071,26 +1066,6 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path Exceptions.Condition_always_true_false (desc, not (IntLit.iszero i), __POS__) in let pre_opt = State.get_normalized_pre (Abs.abstract_no_symop current_pname) in Reporting.log_warning current_pname ~pre: pre_opt exn - | Sil.BinOp ((Binop.Eq | Binop.Ne), lhs, rhs) - when true_branch && !Config.footprint && not (is_comparison_to_nil rhs) -> - (* iOS: check that NSNumber *'s are not used in conditionals without comparing to nil *) - let lhs_normal = Prop.exp_normalize_prop prop__ lhs in - let is_nsnumber = function - | Typ.Tvar (Typename.TN_csu (Csu.Class _, name)) -> - Mangled.to_string name = "NSNumber" - | _ -> false in - let lhs_is_ns_ptr () = - IList.exists - (function - | Sil.Hpointsto (_, Sil.Eexp (exp, _), Sil.Sizeof (Typ.Tptr (typ, _), _, _)) -> - Sil.exp_equal exp lhs_normal && is_nsnumber typ - | _ -> false) - (Prop.get_sigma prop__) in - if not (Sil.exp_is_zero lhs_normal) && lhs_is_ns_ptr () then - let node = State.get_node () in - let desc = Errdesc.explain_bad_pointer_comparison lhs node loc in - let exn = Exceptions.Bad_pointer_comparison (desc, __POS__) in - Reporting.log_warning current_pname exn | _ -> () in if not Config.report_runtime_exceptions then check_already_dereferenced current_pname cond prop__; diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 0b8871e91..f659ef7bf 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -270,6 +270,44 @@ let captured_cxx_ref_in_objc_block_warning stmt_info captured_vars = else None +(* BAD_POINTER_COMPARISON: Fires whenever a NSNumber is dangerously coerced to + a boolean in a comparison *) +let bad_pointer_comparison_warning stmt_info stmts = + let rec condition stmts = + let condition_aux stmt = + match stmt with + | Clang_ast_t.CallExpr _ + | Clang_ast_t.CXXMemberCallExpr _ + | Clang_ast_t.CXXOperatorCallExpr _ + | Clang_ast_t.ObjCMessageExpr _ -> false + | Clang_ast_t.BinaryOperator (_, _, _, boi) + when (boi.boi_kind = `NE) || (boi.boi_kind = `EQ) -> false + | Clang_ast_t.UnaryOperator (_, stmts, _, uoi) when uoi.uoi_kind = `LNot -> + condition stmts + | stmt -> + match Clang_ast_proj.get_expr_tuple stmt with + | Some (_, stmts, expr_info) -> + let typ = CFrontend_utils.Ast_utils.get_desugared_type expr_info.ei_type_ptr in + if CFrontend_utils.Ast_utils.is_ptr_to_objc_class typ "NSNumber" then + true + else + condition stmts + | _ -> false in + IList.exists condition_aux stmts in + if condition stmts then + Some { CIssue. + issue = CIssue.Bad_pointer_comparison; + description = "Implicitly checking whether NSNumber pointer is nil"; + suggestion = + Some ("Did you mean to compare against the unboxed value instead? " ^ + "Please either explicitly compare the NSNumber instance to nil, " ^ + "or use one of the NSNumber accessors before the comparison."); + loc = location_from_sinfo stmt_info + } + else + None + + (* exist m1: m1.body|- EF call_method(addObserver:) => exists m2 : m2.body |- EF call_method(removeObserver:) *) let checker_NSNotificationCenter decl_info decls = let exists_method_calling_addObserver = diff --git a/infer/src/clang/cFrontend_checkers.mli b/infer/src/clang/cFrontend_checkers.mli index c7c07d8ce..9e5807a83 100644 --- a/infer/src/clang/cFrontend_checkers.mli +++ b/infer/src/clang/cFrontend_checkers.mli @@ -29,6 +29,9 @@ val direct_atomic_property_access_warning : Clang_ast_t.decl -> Clang_ast_t.stmt val captured_cxx_ref_in_objc_block_warning : Clang_ast_t.stmt_info -> Clang_ast_t.block_captured_variable list -> CIssue.issue_desc option +val bad_pointer_comparison_warning : + Clang_ast_t.stmt_info -> Clang_ast_t.stmt list -> CIssue.issue_desc option + (* REGISTERED_OBSERVER_BEING_DEALLOCATED: an object is registered in a notification center but not removed before deallocation *) val checker_NSNotificationCenter : Clang_ast_t.decl_info -> Clang_ast_t.decl list -> diff --git a/infer/src/clang/cFrontend_checkers_main.ml b/infer/src/clang/cFrontend_checkers_main.ml index 2514a7eec..ea5f0fb5f 100644 --- a/infer/src/clang/cFrontend_checkers_main.ml +++ b/infer/src/clang/cFrontend_checkers_main.ml @@ -9,7 +9,7 @@ let rec do_frontend_checks_stmt cfg cg method_decl stmt = CFrontend_errors.run_frontend_checkers_on_stmt cfg cg method_decl stmt; - let _, stmts = Clang_ast_proj.get_stmt_tuple stmt in + let stmts = CFrontend_utils.Ast_utils.get_stmts_from_stmt stmt in IList.iter (do_frontend_checks_stmt cfg cg method_decl) stmts let rec do_frontend_checks_decl cfg cg decl = diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index 254fdf428..116231e75 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -47,6 +47,36 @@ let global_var_checker_list = [CFrontend_checkers.global_var_init_with_calls_war let checker_for_global_var dec checker = checker dec +(* List of checkers on conditional operator *) +let conditional_op_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] + +(* Invocation of checker belonging to conditional_op_checker_list *) +let checker_for_conditional_op stmt_info first_stmt checker = + checker stmt_info first_stmt + +(* List of checkers on if-statement *) +let if_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] + +(* Invocation of checker belonging to if_stmt_checker_list *) +let checker_for_if_stmt stmt_info cond checker = + checker stmt_info cond + +(* List of checkers on for statement *) +let for_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] + +(* Invocation of checker belonging to for_stmt_checker_list *) +let checker_for_for_stmt stmt_info cond checker = + checker stmt_info cond + +(* List of checkers on while statement *) +let while_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] + +(* Invocation of checker belonging to while_stmt_checker_list *) +let checker_for_while_stmt stmt_info cond checker = + checker stmt_info cond + + + let errLogMap = ref Procname.Map.empty let get_err_log cfg cg method_decl_opt loc = @@ -103,6 +133,18 @@ let run_frontend_checkers_on_stmt cfg cg method_decl instr = let call_captured_vars_checker = checkers_for_capture_vars stmt_info captured_block_vars in let decl_opt = Some method_decl in invoke_set_of_checkers call_captured_vars_checker cfg cg decl_opt captured_vars_checker_list + | IfStmt (stmt_info, _ :: cond :: _) -> + let call_checker = checker_for_if_stmt stmt_info [cond] in + invoke_set_of_checkers call_checker cfg cg None if_stmt_checker_list + | ConditionalOperator (stmt_info, first_stmt :: _, _) -> + let call_checker = checker_for_conditional_op stmt_info [first_stmt] in + invoke_set_of_checkers call_checker cfg cg None conditional_op_checker_list + | ForStmt (stmt_info, [_; _; cond; _; _]) -> + let call_checker = checker_for_for_stmt stmt_info [cond] in + invoke_set_of_checkers call_checker cfg cg None for_stmt_checker_list + | WhileStmt (stmt_info, [_; cond; _]) -> + let call_checker = checker_for_while_stmt stmt_info [cond] in + invoke_set_of_checkers call_checker cfg cg None while_stmt_checker_list | _ -> () let run_frontend_checkers_on_decl cfg cg dec = diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 661af960c..0afb8b69c 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -424,6 +424,18 @@ struct | Config.OBJCPP -> true | _ -> false + let is_ptr_to_objc_class typ class_name = + match typ with + | Some Clang_ast_t.ObjCObjectPointerType (_, typ_ptr) -> + (match get_desugared_type typ_ptr with + | Some ObjCInterfaceType (_, ptr) -> + (match get_decl ptr with + | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> + String.compare ndi.ni_name class_name = 0 + | _ -> false) + | _ -> false) + | _ -> false + (* let rec getter_attribute_opt attributes = match attributes with diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index dd91b142e..af540aa19 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -149,6 +149,8 @@ sig (* true if CFrontend_config.language is set ot ObjC *) val is_objcpp : unit -> bool + val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool + end module General_utils : diff --git a/infer/src/clang/cIssue.ml b/infer/src/clang/cIssue.ml index 90874e105..71e1c8a27 100644 --- a/infer/src/clang/cIssue.ml +++ b/infer/src/clang/cIssue.ml @@ -9,6 +9,7 @@ type issue = | Assign_pointer_warning + | Bad_pointer_comparison | Cxx_reference_captured_in_objc_block | Direct_atomic_property_access | Global_variable_initialized_with_function_or_method_call @@ -18,6 +19,7 @@ type issue = let to_string issue = match issue with | Assign_pointer_warning -> "ASSIGN_POINTER_WARNING" + | Bad_pointer_comparison -> "BAD_POINTER_COMPARISON" | Cxx_reference_captured_in_objc_block -> "CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK" | Direct_atomic_property_access -> "DIRECT_ATOMIC_PROPERTY_ACCESS" @@ -30,6 +32,7 @@ let to_string issue = let severity_of_issue issue = match issue with | Assign_pointer_warning + | Bad_pointer_comparison | Cxx_reference_captured_in_objc_block | Direct_atomic_property_access | Global_variable_initialized_with_function_or_method_call diff --git a/infer/src/clang/cIssue.mli b/infer/src/clang/cIssue.mli index 27f1b3dcb..b991a33dd 100644 --- a/infer/src/clang/cIssue.mli +++ b/infer/src/clang/cIssue.mli @@ -9,6 +9,7 @@ type issue = | Assign_pointer_warning + | Bad_pointer_comparison | Cxx_reference_captured_in_objc_block | Direct_atomic_property_access | Global_variable_initialized_with_function_or_method_call diff --git a/infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/badpointer.m b/infer/tests/codetoanalyze/objc/linters/badpointer.m similarity index 100% rename from infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/badpointer.m rename to infer/tests/codetoanalyze/objc/linters/badpointer.m diff --git a/infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/nsnumber.m b/infer/tests/codetoanalyze/objc/linters/nsnumber.m similarity index 56% rename from infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/nsnumber.m rename to infer/tests/codetoanalyze/objc/linters/nsnumber.m index 356a67456..e81b3be1e 100644 --- a/infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/nsnumber.m +++ b/infer/tests/codetoanalyze/objc/linters/nsnumber.m @@ -19,22 +19,52 @@ void bad2(NSNumber* isNum) { } } -void ok1(NSNumber* isNum) { +void bad3(NSNumber* number1, NSNumber* number2) { + if (number1 == nil || number2) { + } +} + +@interface TestClass : NSObject + +@property(atomic) int value; + +- (BOOL)doStuff:(NSNumber*)number; + +@end + +@implementation TestClass + +- (BOOL)doStuff:(NSNumber*)number { + return YES; +} + +@end + +void bad4(NSNumber* number, TestClass* t) { t.value = number ? 1 : 0; } + +void ok1(NSNumber* number, TestClass* t) { t.value = number == nil ? 1 : 0; } + +void ok2(NSNumber* number, TestClass* t) { + if ([t doStuff:number]) { + } +} + +void ok3(NSNumber* isNum) { if (isNum != nil) { } } -void ok2(NSNumber* isNum) { +void ok4(NSNumber* isNum) { if (nil != isNum) { } } -void ok3(NSNumber* isNum) { +void ok5(NSNumber* isNum) { if (nil == isNum) { } } -void ok4(NSNumber* isNum) { +void ok6(NSNumber* isNum) { if (isNum == nil) { } } diff --git a/infer/tests/endtoend/objc/infer/NSNumber2Test.java b/infer/tests/endtoend/objc/linters/NSNumber2Test.java similarity index 79% rename from infer/tests/endtoend/objc/infer/NSNumber2Test.java rename to infer/tests/endtoend/objc/linters/NSNumber2Test.java index 3b30ab227..961f73491 100644 --- a/infer/tests/endtoend/objc/infer/NSNumber2Test.java +++ b/infer/tests/endtoend/objc/linters/NSNumber2Test.java @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -package endtoend.objc.infer; +package endtoend.objc.linters; import static org.hamcrest.MatcherAssert.assertThat; -import static utils.matchers.ResultContainsExactly.containsExactly; +import static utils.matchers.ResultContainsLineNumbers.containsLines; import com.google.common.collect.ImmutableList; @@ -28,7 +28,7 @@ import utils.InferRunner; public class NSNumber2Test { public static final String NSNUMBER_FILE = - "infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/badpointer.m"; + "infer/tests/codetoanalyze/objc/linters/badpointer.m"; private static ImmutableList inferCmd; @@ -48,20 +48,10 @@ public class NSNumber2Test { public void badNSNumberPointerComparisonShouldBeFound() throws InterruptedException, IOException, InferException { InferResults inferResults = InferRunner.runInferObjC(inferCmd); - String[] methods = { - "bad1", - "bad2", - "bad3" - }; assertThat( "Results should contain " + BAD_POINTER_COMPARISON, inferResults, - containsExactly( - BAD_POINTER_COMPARISON, - NSNUMBER_FILE, - methods - ) - ); + containsLines(new int[] {17, 26, 33})); } } diff --git a/infer/tests/endtoend/objc/infer/NSNumberTest.java b/infer/tests/endtoend/objc/linters/NSNumberTest.java similarity index 80% rename from infer/tests/endtoend/objc/infer/NSNumberTest.java rename to infer/tests/endtoend/objc/linters/NSNumberTest.java index ec82aa364..0ccc97b8a 100644 --- a/infer/tests/endtoend/objc/infer/NSNumberTest.java +++ b/infer/tests/endtoend/objc/linters/NSNumberTest.java @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -package endtoend.objc.infer; +package endtoend.objc.linters; import static org.hamcrest.MatcherAssert.assertThat; -import static utils.matchers.ResultContainsExactly.containsExactly; +import static utils.matchers.ResultContainsLineNumbers.containsLines; import com.google.common.collect.ImmutableList; @@ -28,7 +28,7 @@ import utils.InferRunner; public class NSNumberTest { public static final String NSNUMBER_FILE = - "infer/tests/codetoanalyze/objc/errors/bad_ptr_comparisons/nsnumber.m"; + "infer/tests/codetoanalyze/objc/linters/nsnumber.m"; private static ImmutableList inferCmd; @@ -48,18 +48,10 @@ public class NSNumberTest { public void badNSNumberPointerComparisonShouldBeFound() throws InterruptedException, IOException, InferException { InferResults inferResults = InferRunner.runInferObjC(inferCmd); - String[] methods = { - "bad1", - "bad2" - }; assertThat( "Results should contain " + BAD_POINTER_COMPARISON, inferResults, - containsExactly( - BAD_POINTER_COMPARISON, - NSNUMBER_FILE, - methods - ) + containsLines(new int[]{13, 18, 23, 43}) ); } diff --git a/infer/tests/utils/InferResults.java b/infer/tests/utils/InferResults.java index 2912484cd..96a40da09 100644 --- a/infer/tests/utils/InferResults.java +++ b/infer/tests/utils/InferResults.java @@ -67,6 +67,7 @@ public class InferResults { errorType.equals("PARAMETER_NOT_NULL_CHECKED") || errorType.equals("DANGLING_POINTER_DEREFERENCE") || errorType.equals("IVAR_NOT_NULL_CHECKED") || + errorType.equals("BAD_POINTER_COMPARISON") || errorType.startsWith("ERADICATE")) { Integer errorLine = Integer.parseInt(items[5].trim()); String procedure = items[6];