PageSourceSearch

https://fbinfer.com/assets/js/c359af60.dcae3aad.js

js fbinfer.com collected 2026-09-24 17:55:34 UTC 206,474 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunk=globalThis.webpackChunk||[]).push([[2316],{3476(e,n,s){s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>o});const r=JSON.parse('{"id":"all-issue-types","title":"List of all issue types","description":"Here is an overview of the issue types currently reported by Infer.","source":"@site/docs/all-issue-types.md","sourceDirName":".","slug":"/all-issue-types","permalink":"/docs/next/all-issue-types","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"title":"List of all issue types"},"sidebar":"docs","previous":{"title":"List of all categories of issue types","permalink":"/docs/next/all-categories"},"next":{"title":"Annotation Reachability","permalink":"/docs/next/checker-annotation-reachability"}}');var i=s(4848),t=s(8453);const l={title:"List of all issue types"},c=void 0,a={},o=[{value:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK",id:"arbitrary_code_execution_under_lock",level:2},{value:"BAD_ARG",id:"bad_arg",level:2},{value:"BAD_ARG_LATENT",id:"bad_arg_latent",level:2},{value:"BAD_GENERATOR",id:"bad_generator",level:2},{value:"BAD_GENERATOR_LATENT",id:"bad_generator_latent",level:2},{value:"BAD_KEY",id:"bad_key",level:2},{value:"BAD_KEY_LATENT",id:"bad_key_latent",level:2},{value:"BAD_MAP",id:"bad_map",level:2},{value:"BAD_MAP_LATENT",id:"bad_map_latent",level:2},{value:"BAD_RECORD",id:"bad_record",level:2},{value:"BAD_RECORD_LATENT",id:"bad_record_latent",level:2},{value:"BAD_RETURN",id:"bad_return",level:2},{value:"BAD_RETURN_LATENT",id:"bad_return_latent",level:2},{value:"BLOCK_PARAMETER_NOT_NULL_CHECKED",id:"block_parameter_not_null_checked",level:2},{value:"BUFFER_OVERRUN_L1",id:"buffer_overrun_l1",level:2},{value:"BUFFER_OVERRUN_L2",id:"buffer_overrun_l2",level:2},{value:"BUFFER_OVERRUN_L3",id:"buffer_overrun_l3",level:2},{value:"BUFFER_OVERRUN_L4",id:"buffer_overrun_l4",level:2},{value:"BUFFER_OVERRUN_L5",id:"buffer_overrun_l5",level:2},{value:"BUFFER_OVERRUN_S2",id:"buffer_overrun_s2",level:2},{value:"BUFFER_OVERRUN_U5",id:"buffer_overrun_u5",level:2},{value:"CAPTURED_STRONG_SELF",id:"captured_strong_self",level:2},{value:"CHECKERS_ALLOCATES_MEMORY",id:"checkers_allocates_memory",level:2},{value:"CHECKERS_ANNOTATION_REACHABILITY_ERROR",id:"checkers_annotation_reachability_error",level:2},{value:"CHECKERS_CALLS_EXPENSIVE_METHOD",id:"checkers_calls_expensive_method",level:2},{value:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED",id:"checkers_expensive_overrides_unannotated",level:2},{value:"CHECKERS_FRAGMENT_RETAINS_VIEW",id:"checkers_fragment_retains_view",level:2},{value:"COMPARED_TO_NULL_AND_DEREFERENCED",id:"compared_to_null_and_dereferenced",level:2},{value:"CONFIG_GATED",id:"config_gated",level:2},{value:"CONFIG_IMPACT",id:"config_impact",level:2},{value:"CONFIG_IMPACT_STRICT",id:"config_impact_strict",level:2},{value:"CONFIG_UNGATED",id:"config_ungated",level:2},{value:"CONFIG_USAGE",id:"config_usage",level:2},{value:"CONSTANT_ADDRESS_DEREFERENCE",id:"constant_address_dereference",level:2},{value:"CONSTANT_ADDRESS_DEREFERENCE_LATENT",id:"constant_address_dereference_latent",level:2},{value:"CXX_REF_CAPTURED_IN_BLOCK",id:"cxx_ref_captured_in_block",level:2},{value:"CXX_STRING_CAPTURED_IN_BLOCK",id:"cxx_string_captured_in_block",level:2},{value:"DATA_FLOW_TO_SINK",id:"data_flow_to_sink",level:2},{value:"DEADLOCK",id:"deadlock",level:2},{value:"DEAD_STORE",id:"dead_store",level:2},{value:"EXECUTION_TIME_COMPLEXITY_INCREASE",id:"execution_time_complexity_increase",level:2},{value:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD",id:"execution_time_complexity_increase_ui_thread",level:2},{value:"EXECUTION_TIME_UNREACHABLE_AT_EXIT",id:"execution_time_unreachable_at_exit",level:2},{value:"EXPENSIVE_EXECUTION_TIME",id:"expensive_execution_time",level:2},{value:"EXPENSIVE_LOOP_INVARIANT_CALL",id:"expensive_loop_invariant_call",level:2},{value:"GUARDEDBY_VIOLATION",id:"guardedby_violation",level:2},{value:"IMPURE_FUNCTION",id:"impure_function",level:2},{value:"INEFFICIENT_KEYSET_ITERATOR",id:"inefficient_keyset_iterator",level:2},{value:"INFERBO_ALLOC_IS_BIG",id:"inferbo_alloc_is_big",level:2},{value:"INFERBO_ALLOC_IS_NEGATIVE",id:"inferbo_alloc_is_negative",level:2},{value:"INFERBO_ALLOC_IS_ZERO",id:"inferbo_alloc_is_zero",level:2},{value:"INFERBO_ALLOC_MAY_BE_BIG",id:"inferbo_alloc_may_be_big",level:2},{value:"INFERBO_ALLOC_MAY_BE_NEGATIVE",id:"inferbo_alloc_may_be_negative",level:2}
1,{value:"INFINITE_EXECUTION_TIME",id:"infinite_execution_time",level:2},{value:"Example 1: T due to expressivity",id:"example-1-t-due-to-expressivity",level:3},{value:"Example 2: T due to unmodeled calls",id:"example-2-t-due-to-unmodeled-calls",level:3},{value:"Example 3: T due to calling another T-costed function",id:"example-3-t-due-to-calling-another-t-costed-function",level:3},{value:"INFINITE_LOOP",id:"infinite_loop",level:2},{value:"INFINITE_RECURSION",id:"infinite_recursion",level:2},{value:"INTEGER_OVERFLOW_L1",id:"integer_overflow_l1",level:2},{value:"INTEGER_OVERFLOW_L2",id:"integer_overflow_l2",level:2},{value:"INTEGER_OVERFLOW_L5",id:"integer_overflow_l5",level:2},{value:"INTEGER_OVERFLOW_U5",id:"integer_overflow_u5",level:2},{value:"INTERFACE_NOT_THREAD_SAFE",id:"interface_not_thread_safe",level:2},{value:"INVALID_SIL",id:"invalid_sil",level:2},{value:"INVARIANT_CALL",id:"invariant_call",level:2},{value:"IPC_ON_UI_THREAD",id:"ipc_on_ui_thread",level:2},{value:"LAB_RESOURCE_LEAK",id:"lab_resource_leak",level:2},{value:"LINEAGE_FLOW",id:"lineage_flow",level:2},{value:"LOCKLESS_VIOLATION",id:"lockless_violation",level:2},{value:"LOCK_CONSISTENCY_VIOLATION",id:"lock_consistency_violation",level:2},{value:"Fixing Lock Consistency Violation reports",id:"fixing-lock-consistency-violation-reports",level:3},{value:"LOCK_ON_UI_THREAD",id:"lock_on_ui_thread",level:2},{value:"MEMORY_LEAK_C",id:"memory_leak_c",level:2},{value:"Memory leak in C",id:"memory-leak-in-c",level:3},{value:"Memory leak in Objective-C",id:"memory-leak-in-objective-c",level:3},{value:"MEMORY_LEAK_CPP",id:"memory_leak_cpp",level:2},{value:"MISSING_NULLABILITY_ANNOTATION",id:"missing_nullability_annotation",level:2}
1,{value:"Why this matters",id:"why-this-matters",level:3},{value:"Example",id:"example",level:3},{value:"Preferred fix: annotate the Objective-C header",id:"preferred-fix-annotate-the-objective-c-header",level:3},{value:"Workaround when you cannot edit the header",id:"workaround-when-you-cannot-edit-the-header",level:3},{value:"MISSING_NULLABILITY_ANNOTATION_PULSE",id:"missing_nullability_annotation_pulse",level:2},{value:"Why this matters",id:"why-this-matters-1",level:3},{value:"Example",id:"example-1",level:3},{value:"Preferred fix: annotate the Objective-C header",id:"preferred-fix-annotate-the-objective-c-header-1",level:3},{value:"Workaround when you cannot edit the header",id:"workaround-when-you-cannot-edit-the-header-1",level:3},{value:"MISSING_REQUIRED_PROP",id:"missing_required_prop",level:2},{value:"Examples",id:"examples",level:2},{value:"MIXED_SELF_WEAKSELF",id:"mixed_self_weakself",level:2},{value:"MODIFIES_IMMUTABLE",id:"modifies_immutable",level:2},{value:"MULTIPLE_WEAKSELF",id:"multiple_weakself",level:2},{value:"MUTUAL_RECURSION_CYCLE",id:"mutual_recursion_cycle",level:2},{value:"NIL_BLOCK_CALL",id:"nil_block_call",level:2},{value:"NIL_BLOCK_CALL_LATENT",id:"nil_block_call_latent",level:2},{value:"NIL_INSERTION_INTO_COLLECTION",id:"nil_insertion_into_collection",level:2},{value:"Arrays",id:"arrays",level:3},{value:"Dictionaries",id:"dictionaries",level:3},{value:"NIL_INSERTION_INTO_COLLECTION_LATENT",id:"nil_insertion_into_collection_latent",level:2},{value:"NIL_MESSAGING_TO_NON_POD",id:"nil_messaging_to_non_pod",level:2},{value:"NIL_MESSAGING_TO_NON_POD_LATENT",id:"nil_messaging_to_non_pod_latent",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY",id:"no_matching_branch_in_try",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY_LATENT",id:"no_matching_branch_in_try_latent",level:2},{value:"NO_MATCHING_CASE_CLAUSE",id:"no_matching_case_clause",level:2},{value:"NO_MATCHING_CASE_CLAUSE_LATENT",id:"no_matching_case_clause_latent",level:2},{value:"NO_MATCHING_ELSE_CLAUSE",id:"no_matching_else_clause",level:2},{value:"NO_MATCHING_ELSE_CLAUSE_LATENT",id:"no_matching_else_clause_latent",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE",id:"no_matching_function_clause",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE_LATENT",id:"no_matching_function_clause_latent",level:2},{value:"NO_MATCH_OF_RHS",id:"no_match_of_rhs",level:2},{value:"NO_MATCH_OF_RHS_LATENT",id:"no_match_of_rhs_latent",level:2},{value:"NO_TRUE_BRANCH_IN_IF",id:"no_true_branch_in_if",level:2},{value:"NO_TRUE_BRANCH_IN_IF_LATENT",id:"no_true_branch_in_if_latent",level:2},{value:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK",id:"nsstring_internal_ptr_captured_in_block",level:2},{value:"NULLPTR_DEREFERENCE",id:"nullptr_dereference",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java",level:3},{value:"Null dereference in C",id:"null-dereference-in-c",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS",id:"nullptr_dereference_in_nullsafe_class",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java-1",level:3},{value:"Null dereference in C",id:"null-dereference-in-c-1",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c-1",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT",id:"nullptr_dereference_in_nullsafe_class_latent",level:2},{value:"NULLPTR_DEREFERENCE_LATENT",id:"nullptr_dereference_latent",level:2},{value:"NULL_ARGUMENT",id:"null_argument",level:2},{value:"NULL_ARGUMENT_LATENT",id:"null_argument_latent",level:2},{value:"OPTIONAL_EMPTY_ACCESS",id:"optional_empty_access",level:2},{value:"OPTIONAL_EMPTY_ACCESS_LATENT",id:"optional_empty_access_latent",level:2},{value:"PULSE_ASSERTION_ERROR",id:"pulse_assertion_error",level:2},{value:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS",id:"pulse_cannot_instantiate_abstract_class",level:2},{value:"PULSE_CONST_REFABLE",id:"pulse_const_refable",level:2},{value:"PULSE_DICT_MISSING_KEY",id:"pulse_dict_missing_key",level:2},{value:"PULSE_DYNAMIC_TYPE_MISMATCH",id:"pulse_dynamic_type_mismatch",level:2},{value:"PULSE_READONLY_SHARED_PTR_PARAM",id:"pulse_readonly_shared_ptr_param",level:2},{value:"PULSE_REFERENCE_STABILITY",id:"pulse_reference_stability",level:2},{value:"PULSE_RESOURCE_LEAK",id:"pulse_resource_leak",level:2},{value:"PULSE_TRANSITIVE_ACCESS",id:"pulse_transitive_access",level:2},{value:"PULSE_UNAWAITED_AWAITABLE",id:"pulse_unawaited_awaitable",level:2},{value:"PULSE_UNFINISHED_BUILDER",id:"pulse_unfinished_builder",level:2},{value:"PULSE_UNINITIALIZED_CONST",id:"pulse_uninitialized_const",level:2}
1,{value:"PULSE_UNINITIALIZED_METHOD",id:"pulse_uninitialized_method",level:2},{value:"PULSE_UNINITIALIZED_VALUE",id:"pulse_uninitialized_value",level:2},{value:"PULSE_UNNECESSARY_COPY",id:"pulse_unnecessary_copy",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT",id:"pulse_unnecessary_copy_assignment",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST",id:"pulse_unnecessary_copy_assignment_const",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE",id:"pulse_unnecessary_copy_assignment_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE",id:"pulse_unnecessary_copy_intermediate",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST",id:"pulse_unnecessary_copy_intermediate_const",level:2},{value:"PULSE_UNNECESSARY_COPY_MOVABLE",id:"pulse_unnecessary_copy_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL",id:"pulse_unnecessary_copy_optional",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST",id:"pulse_unnecessary_copy_optional_const",level:2},{value:"PULSE_UNNECESSARY_COPY_RETURN",id:"pulse_unnecessary_copy_return",level:2},{value:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT",id:"pulse_unnecessary_copy_thrift_assignment",level:2},{value:"PURE_FUNCTION",id:"pure_function",level:2},{value:"REGEX_OP_ON_UI_THREAD",id:"regex_op_on_ui_thread",level:2},{value:"RETAIN_CYCLE",id:"retain_cycle",level:2},{value:"RETAIN_CYCLE_NO_WEAK_INFO",id:"retain_cycle_no_weak_info",level:2},{value:"SCOPE_LEAKAGE",id:"scope_leakage",level:2},{value:"SELF_IN_BLOCK_PASSED_TO_INIT",id:"self_in_block_passed_to_init",level:2},{value:"SENSITIVE_DATA_FLOW",id:"sensitive_data_flow",level:2},{value:"STACK_VARIABLE_ADDRESS_ESCAPE",id:"stack_variable_address_escape",level:2},{value:"STARVATION",id:"starvation",level:2},{value:"STATIC_CONSTRUCTOR_STALL",id:"static_constructor_stall",level:2},{value:"STATIC_INITIALIZATION_ORDER_FIASCO",id:"static_initialization_order_fiasco",level:2},{value:"STRICT_MODE_VIOLATION",id:"strict_mode_violation",level:2},{value:"STRONG_SELF_NOT_CHECKED",id:"strong_self_not_checked",level:2},{value:"SWIFT_NPE",id:"swift_npe",level:2},{value:"Force-unwrap of an Optional whose <code>nil</code> case is reachable",id:"force-unwrap-of-an-optional-whose-nil-case-is-reachable",level:2},{value:"Implicitly Unwrapped Optional (<code>T!</code>) whose underlying value is <code>nil</code>
1",id:"implicitly-unwrapped-optional-t-whose-underlying-value-is-nil",level:2},{value:"<code>Optional.unsafelyUnwrapped</code> on a known-<code>nil</code> receiver",id:"optionalunsafelyunwrapped-on-a-known-nil-receiver",level:2},{value:"SWIFT_NPE_LATENT",id:"swift_npe_latent",level:2},{value:"TAINT_ERROR",id:"taint_error",level:2},{value:"THREAD_SAFETY_VIOLATION",id:"thread_safety_violation",level:2},{value:"Thread-safety: What is a data race",id:"thread-safety-what-is-a-data-race",level:3},{value:"Thread-safety: Potential fixes",id:"thread-safety-potential-fixes",level:3},{value:"Thread-safety: Conditions checked before reporting",id:"thread-safety-conditions-checked-before-reporting",level:3},{value:"Thread-safety: Thread annotations recognized by RacerD",id:"thread-safety-thread-annotations-recognized-by-racerd",level:3},{value:"Thread-safety: Other annotations and what they do",id:"thread-safety-other-annotations-and-what-they-do",level:3},{value:"TOPL_ERROR",id:"topl_error",level:2},{value:"TOPL_ERROR_LATENT",id:"topl_error_latent",level:2},{value:"USE_AFTER_DELETE",id:"use_after_delete",level:2},{value:"USE_AFTER_DELETE_LATENT",id:"use_after_delete_latent",level:2},{value:"USE_AFTER_FREE",id:"use_after_free",level:2},{value:"USE_AFTER_FREE_LATENT",id:"use_after_free_latent",level:2},{value:"USE_AFTER_LIFETIME",id:"use_after_lifetime",level:2},{value:"USE_AFTER_LIFETIME_LATENT",id:"use_after_lifetime_latent",level:2},{value:"VECTOR_INVALIDATION",id:"vector_invalidation",level:2},{value:"VECTOR_INVALIDATION_LATENT",id:"vector_invalidation_latent",level:2},{value:"WEAK_SELF_IN_NO_ESCAPE_BLOCK",id:"weak_self_in_no_escape_block",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Here is an overview of the issue types currently reported by Infer."}),"\n",(0,i.jsx)(n.h2,{id:"arbitrary_code_execution_under_lock",children:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Arbitrary Code Execution Under lock" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A call that may execute arbitrary code (such as registered, or chained, callbacks) is made while holding a lock.\nThis code may deadlock whenever the callbacks obtain locks themselves, so it is an unsafe pattern."}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  SettableFuture future = null;\n\n  public void callFutureSet() {\n    future.set(null);\n  }\n\n  // synchronized means it's taking a lock implicitly\n  public synchronized void example_of_bad_pattern() {\n    callFutureSet(); // <- issue reported here\n  }\n\n  // If the call is made while holding multiple locks, the warning\n  // will be issued only at the innermost lock acquisition. Here we\n  // report in example_of_bad_pattern but we won't report below.\n  public void nested_bad_pattern_no_report(Object o) {\n    synchronized (o) {\n      example_of_bad_pattern(); // <- no issue reported\n    }\n  }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"bad_arg",children:"BAD_ARG"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Bad arg in Erlang: Reports an error when the type of an argument is wrong or the argument is badly formed. Corresponds to the ",(0,i.jsx)(n.code,{children:"badarg"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, trying to concatenate the number ",(0,i.jsx)(n.code,{children:"3"})," with  the list ",(0,i.jsx)(n.code,{children:"[1,2]"})," gives ",(0,i.jsx)(n.code,{children:"badarg"})," error because ",(0,i.jsx)(n.code,{children:"3"})," is not a list."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"f() ->\n    3 ++ [1,2]. // badarg error\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that although the first argument needs to be a list, the second argument may not be a list.\nFor instance, concatenating [1,2] 
1with the number ",(0,i.jsx)(n.code,{children:"3"})," raises no error in Erlang."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"g() ->\n    [1,2] ++ 3. // no error. Result: [1,2|3]\n"})}),"\n",(0,i.jsx)(n.h2,{id:"bad_arg_latent",children:"BAD_ARG_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_arg",children:"BAD_ARG"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_generator",children:"BAD_GENERATOR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Bad generator in Erlang: Reports an error when a wrong type is used in a generator. Corresponds to the ",(0,i.jsx)(n.code,{children:"bad_generator"})," error in the Erlang runtime."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"list_instead_of_map() ->\n    M = [],\n    [{K, V} || K := V <- M]\n"})}),"\n",(0,i.jsx)(n.h2,{id:"bad_generator_latent",children:"BAD_GENERATOR_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_generator",children:"BAD_GENERATOR"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_key",children:"BAD_KEY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Bad key in Erlang: Reports an error when trying to access or update a non-existing key in a map. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badkey,K}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, trying to update the key ",(0,i.jsx)(n.code,{children:"2"})," in ",(0,i.jsx)(n.code,{children:"M"})," gives ",(0,i.jsx)(n.code,{children:"{badkey,2}"})," error because ",(0,i.jsx)(n.code,{children:"2"})," is not present as a key in ",(0,i.jsx)(n.code,{children:"M"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"f() ->\n    M = #{},\n    M#{2 := 3}.\n"})}),"\n",(0,i.jsx)(n.p,{children:"Note that maps currently use a recency abstraction, meaning that only the most recent key/value is tracked.\nTherefore, if a map is non-empty and we try to access a key other than the one we track, we just assume that it is there to avoid false positives."}),"\n",(0,i.jsx)(n.h2,{id:"bad_key_latent",children:"BAD_KEY_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_key",children:"BAD_KEY"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_map",children:"BAD_MAP"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Bad map in Erlang: Reports an error when trying to access or update a key for a term that is not a map. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badmap,...}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, trying to update ",(0,i.jsx)(n.code,{children:"L"})," as if it was a map gives ",(0,i.jsx)(n.code,{children:"{badmap,[1,2,3]}"})," error because ",(0,i.jsx)(n.code,{children:"L"})," is actually a list (",(0,i.jsx)(n.code,{children:"[1,2,3]"}),")."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"f() ->\n    L = [1,2,3],\n    L#{1 => 2}.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"bad_map_latent",children:"BAD_MAP_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_map",children:"BAD_MAP"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_record",children:"BAD_RECORD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Bad record in Erlang: Reports an error when trying to access or update a record with the wrong name. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badrecord,Name}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, accessing ",(0,i.jsx)(n.code,{children:"R"})," as a ",(0,i.jsx)(n.code,{children:"person"})," record gives ",(0,i.jsx)(n.code,{children:"{badrecord,person}"})," error because ",(0,i.jsx)(n.code,{children:"R"})," is ",(0,i.jsx)(n.code,{children:"rabbit"})," (even though both share the ",(0,i.jsx)(n.code,{children:"name"})," field)."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:'-record(person, {name, phone}).\n-record(rabbit, {name, color}).\n\nf() ->\n    R = #rabbit{name = "Bunny", color = "Brown"},\n    R#person.name.\n'})}),"\n",(0,i.jsx)(n.h2,{id:"bad_record_latent",children:"BAD_RECORD_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_record",children:"BAD_RECORD"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_return",children:"BAD_RETURN"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Bad Return" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Bad return in Erlang: The dynamic type of a returned value disagrees with the static type given in the spec."}),"\n",(0,i.jsx)(n.p,{children:"For example, this function returns an integer, while the spec says it returns an atom."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"-spec f() -> atom().\nf() -> 1.\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Note that this will ",(0,i.jsx)(n.em,{children:"not"})," lead to a runtime error when running the Erlang program."]}),"\n",(0,i.jsx)(n.h2,{id:"bad_return_latent",children:"BAD_RETURN_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Bad Return Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#bad_return",children:"BAD_RETURN"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Block Parameter Not Null Checked" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-parameter-not-null-checked",children:"parameter-not-null-checked"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This error type is reported only in Objective-C/Objective-C++. It happens when a method has a block as a parameter,\nand the block is executed in the method's body without checking it for ",(0,i.jsx)(n.code,{children:"nil"})," first. If a ",(0,i.jsx)(n.code,{children:"nil"})," block is passed to\nthe method, then this will cause a crash. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"- (void)uploadTaskWithRequest:(NSURLRequest*)urlRequest\n                       fromFile:(NSURL*)fileURL\n                       delegate:(id)delegate\n                  delegateQueue:(NSOperation
1Queue*)delegateQueue\n                     completion:(void (^)())completion {\n     ...\n    completion();\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nPossible solutions are adding a check for ",(0,i.jsx)(n.code,{children:"nil"}),", or making sure that the method\nis not ever called with ",(0,i.jsx)(n.code,{children:"nil"}),". When an argument will never be ",(0,i.jsx)(n.code,{children:"nil"}),", you can add\nthe annotation ",(0,i.jsx)(n.code,{children:"nonnull"})," to the argument's type, to tell Infer (and the type\nsystem), that the argument won't be ",(0,i.jsx)(n.code,{children:"nil"}),". This will silence the warning."]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun L1" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This is reported when outside of buffer bound is accessed.  It can corrupt memory and may introduce\nsecurity issues in C/C++."}),"\n",(0,i.jsxs)(n.p,{children:["For example, ",(0,i.jsx)(n.code,{children:"int a[3]; a[5] = 42;"})," generates a ",(0,i.jsx)(n.code,{children:"BUFFER_OVERRUN_L1"})," on ",(0,i.jsx)(n.code,{children:"a[5] = 42;"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Buffer overrun reports fall into several "buckets" corresponding to the expected precision of the\nreport.  The higher the number, the more likely it is to be a false positive.'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,i.jsx)(n.em,{children:"must"})," be unsafe.  For example, array size: ",(0,i.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,i.jsx)(n.code,{children:"[5,5]"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,i.jsx)(n.code,{children:"L1"}),", when it ",(0,i.jsx)(n.em,{children:"may"})," be unsafe.  For example, array size:",(0,i.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,i.jsx)(n.code,{children:"[0,5]"}),".  Note that the offset may be a safe value in the real execution, i.e. safe when\n0, 1, or 2; unsafe when 3, 4, or 5."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L5"}),": The least faithful report, when there is an interval top.  For example, array size:\n",(0,i.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,i.jsx)(n.code,{children:"[-oo,+oo]"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L4"}),": More faithful report than ",(0,i.jsx)(n.code,{children:"L5"}),", when there is an infinity value.  For example, array size:\n",(0,i.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,i.jsx)(n.code,{children:"[0, +oo]"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L3"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"S2"}),": An array access is unsafe by symbolic values.  For example, array size: ",(0,i.jsx)(n.code,{children:"[n,n]"}),", offset\n",(0,i.jsx)(n.code,{children:"[n,+oo]"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"U5"}),": An array access is unsafe by unknown values, which are usually from unknown function\ncalls."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_l2",children:"BUFFER_OVERRUN_L2"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun L2" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_l3",children:"BUFFER_OVERRUN_L3"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun L3" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_l4",children:"BUFFER_OVERRUN_L4"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun L4" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_l5",children:"BUFFER_OVERRUN_L5"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun L5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_s2",children:"BUFFER_OVERRUN_S2"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun S2" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"buffer_overrun_u5",children:"BUFFER_OVERRUN_U5"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Buffer Overrun U5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"captured_strong_self",children:"CAPTURED_STRONG_SELF"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Captured strongSelf" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check is about when a strong pointer to ",(0,i.jsx)(n.code,{children:"self"})," is captured in a block.\nThis could lead to retain cycles or unexpected behavior since to avoid retain\ncycles one usually uses a local strong pointer or a captured weak pointer instead."]}),"\n",(0,i.jsx)(n.p,{children:"This will happen in one of two cases generally:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["One uses ",(0,i.jsx)(n.code,{children:"weakSelf"})," but forgot to declare it weak first."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __typeof(self) weakSelf = self;\n  int (^my_block)(BOOL) = ^(BOOL isTapped) {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    return strongSelf->x;\n  };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"})," Replace the first line with ",(0,i.jsx)(n.code,{children:"__weak __typeof(self) weakSelf = self;"}),"."]}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["One is using ",(0,i.jsx)(n.code,{children:"strongSelf"}),", declared in a block, in another inner block.\nThe retain cycle is avoided in the outer block because ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a\nlocal variable of the block. If ",(0,i.jsx)(n.code,{children:"strongSelf"})," is used in the inner block,\nthen it's not a local variable anymore, but a captured variable."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong typeof(self) strongSelf = weakSelf;\n    if (strongSelf) {\n      int (^my_block)() = ^() {\n        int x = strongSelf->x;\n        ...\n      };\n      ...\n    }\n    ...\n  };\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this example, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a captured variable of the inner block, and this could cause retain cycles."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"})," Use a new pointer to self local to the inner block. In the example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong typeof(self) strongSelf = weakSelf;\n    if (strongSelf) {\n      int (^my_block)() = ^() {\n         __typeof(self) innerStrongSelf = weakSelf;\n        int x = innerStrongSelf->x;\n        ...\n      };\n      ...\n    }\n    ...\n  };\n"})}),"\n",(0,i.jsx)(n.p,{children:"Or, to improve readability, move the inner block logic into a separate method."}),"\n",(0,i.jsx)(n.p,{children:"Another solution could be to copy the instance variable that one needs to access inside the inner block to a local variable, and use the local variable instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong typeof(self) strongSelf = weakSelf;\n    if (strongSelf) {\n      int my_x = strongSelf->x;\n      int (^my_block)() = ^() {\n        int x = my_x;\n        ...\n      };\n      ...\n    }\n    ...\n  };\n"})}),"\n",(0,i.jsx)(n.h2,{id:"checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Allocates Memory" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A method annotated with ",(0,i.jsx)(n.code,{children:"@NoAllocation"})," transitively calls ",(0,i.jsx)(n.code,{children:"new"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class C implements I {\n  @NoAllocation\n  void directlyAllocatingMethod() {\n    new Object();\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Annotation Reachability Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A method annotated with an annotation ",(0,i.jsx)(n.code,{children:"@A"})," transitively calls a method annotated ",(0,i.jsx)(n.code,{children:"@B"})," where the combination of annotations is forbidden (for example, ",(0,i.jsx)(n.code,{children:"@UiThread"})," calling ",(0,i.jsx)(n.code,{children:"@WorkerThread"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Expensive Method Called" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A method annotated with ",(0,i.jsx)(n.code,{children:"@PerformanceCritical"})," transitively calls a method annotated ",(0,i.jsx)(n.code,{children:"@Expensive"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class C {\n  @PerformanceCritical\n  void perfCritical() {\n    expensive();\n  }\n\n  @Expensive\n  void expensive() {}\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"checkers_expensive_overrides_unannotated",children:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Expensive Overrides Unannotated" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A method annotated with ",(0,i.jsx)(n.code,{children:"@Expensive"})," overrides an un-annotated method."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"interface I {\n  void foo();\n}\n\nclass A implements I {\n  @Expensive\n  public void foo() {}\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"checkers_fragment_retains_view",children:"CHECKERS_FRAGMENT_RETAINS_VIEW"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Fragment Retains View" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-fragment-retains-view",children:"fragment-retains-view"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This error type is Android-specific. It fires when a ",(0,i.jsx)(n.code,{children:"Fragment"})," type fails to\nnullify one or more of its declared ",(0,i.jsx)(n.code,{children:"View"})," fields in ",(0,i.jsx)(n.code,{children:"onDestroyView"}),". In\nperformance-sensitive applications, a ",(0,i.jsx)(n.code,{children:"Fragment"})," should initialize all ",(0,i.jsx)(n.code,{children:"View"}),"'s\nin ",(0,i.jsx)(n.code,{children:"onCreateView"})," and nullify them in ",(0,i.jsx)(n.code,{children:"onDestroyView"}),". If a ",(0,i.jsx)(n.code,{children:"Fragment"})," is placed\non the back stack and fails to nullify a ",(0,i.jsx)(n.code,{children:"View"})," in ",(0,i.jsx)(n.code,{children:"onDestroyView"}),", it will\nretain a useless reference to that ",(0,i.jsx)(n.code,{children:"View"})," that will not be cleaned up until the\n",(0,i.jsx)(n.code,{children:"Fragment"})," is resumed or destroyed."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Nullify the ",(0,i.jsx)(n.code,{children:"View"})," in question in ",(0,i.jsx)(n.code,{children:"onDestroyView"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Compared To Null And Dereferenced" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A pointer that has both been compared to null, which suggests that it could be null, but has also been dereferenced without a null check."}),"\n",(0,i.jsx)(n.h2,{id:"config_gated",children:"CONFIG_GATED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Config Gated" b
1y ',(0,i.jsx)(n.a,{href:"/docs/next/checker-config-gating",children:"config-gating"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A call site is gated by one or more config flags. Being gated by config X means\nthat changing the value of config X can be used to turn off the execution of the\nreported code."}),"\n",(0,i.jsx)(n.h2,{id:"config_impact",children:"CONFIG_IMPACT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Config Impact" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when an ",(0,i.jsx)(n.em,{children:"expensive"})," function is called without a ",(0,i.jsx)(n.em,{children:"config check"}),".  The\n",(0,i.jsx)(n.em,{children:"config"})," is usually a boolean value that enables experimental new features and it is defined per\napplication/codebase, e.g. gatekeepers.  To determine whether a function is expensive or not, the\nchecker relies on modeled functions that are assumed to be expensive, e.g. string operations,\nregular expression match, or DB accesses."]}),"\n",(0,i.jsxs)(n.p,{children:["Similar to ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"Cost analysis"}),", this issue type is reported only in\ndifferential mode, i.e. when there are original code and modified one and we can compare Infer's\nresults on both of them."]}),"\n",(0,i.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// version1\nfoo();\nif (config_check){\n   bar();\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"which is then modified to next"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// version2\nfoo();\nif (config_check){\n   bar();\n}\ngoo(); // added\n"})}),"\n",(0,i.jsxs)(n.p,{children:['the analysis would warn the developer that "',(0,i.jsx)(n.code,{children:"goo()"}),' is a newly added function call and it might\ncause an unexpected new behavior". However, if we were to add ',(0,i.jsx)(n.code,{children:"goo()"})," right after ",(0,i.jsx)(n.code,{children:"bar()"}),", then\nInfer wouldn't warn about it because it is already gated under the ",(0,i.jsx)(n.code,{children:"config_check"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The analysis is inter-procedural: it can reason about impacts by code changes not only inside a\nsingle procedure, but also the impacts that are propagated by function calls. Thus, if we were to\nmodify ",(0,i.jsx)(n.code,{children:"version1"})," to ",(0,i.jsx)(n.code,{children:"version3"})," below by calling ",(0,i.jsx)(n.code,{children:"goo()"})," in ",(0,i.jsx)(n.code,{children:"foo()"}),","]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// version3\nvoid foo(){\n   // ....\n   goo(); // added\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["then the analysis will report a ",(0,i.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue on the ungated call site of ",(0,i.jsx)(n.code,{children:"foo()"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Currently, the analysis supports both Objective-C and Java but not C++."}),"\n",(0,i.jsx)(n.p,{children:"Action: Make sure the ungated code change is semantically correct and harmless in terms of execution\ncost.  If you are not sure, gate it with a new or pre-existing config."}),"\n",(0,i.jsx)(n.h2,{id:"config_impact_strict",children:"CONFIG_IMPACT_STRICT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#ungated-code",children:"Ungated code"}),'. Reported as "Config Impact Strict" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is similar to ",(0,i.jsxs)(n.a,{href:"#config_impact",children:[(0,i.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue"]})," but the analysis reports ",(0,i.jsx)(n.strong,{children:"all"})," ungated\ncodes irrespective of whether they are expensive or not."]}),"\n",(0,i.jsx)(n.h2,{id:"config_ungated",children:"CONFIG_UNGATED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Config Ungated" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-config-gating",children:"config-gating"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A call site is not gated by any config flag. There is no config value that,\nif changed, would prevent this code from executing."}),"\n",(0,i.jsx)(n.h2,{id:"config_usage",children:"CONFIG_USAGE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Config Usage" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when a ",(0,i.jsx)(n.em,{children:"config"})," value is used as branch condition in a function.  The\n",(0,i.jsx)(n.em,{children:"config"})," is usually a boolean value that enables experimental new features and it is defined per\napplication/codebase, e.g. gatekeepers."]}),"\n",(0,i.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:'void foo() {\n  if(config_check("my_new_feature")){ ... }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:['then analysis would provide information that "the function ',(0,i.jsx)(n.code,{children:"foo"})," uses the config ",(0,i.jsx)(n.code,{children:"my_new_feature"}),' as\nbranch condition".']}),"\n",(0,i.jsx)(n.p,{children:"Note: This type of issue is only for providing semantic information, rather than warning or\nreporting actual problem."}),"\n",(0,i.jsx)(n.h2,{id:"constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Constant Address Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when an address at an absolute location, e.g. 1234,\nis dereferenced. It is a more general version of the\n",(0,i.jsx)(n.a,{href:"#nullptr_dereference",children:(0,i.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," error type that is\nreported when the address is a constant other than zero."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, ",(0,i.jsx)(n.code,{children:"int *p = (int *) 123; *p = 42;"})," generates a ",(0,i.jsx)(n.code,{children:"CONSTANT_ADDRESS_DEREFERENCE"})," on ",(0,i.jsx)(n.code,{children:"*p = 42;"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["For more information see the ",(0,i.jsx)(n.a,{href:"#nullptr_dereference",children:(0,i.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," issue type."]}),"\n",(0,i.jsx)(n.h2,{id:"constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Constant Address Dereference Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}
1),'. Reported as "C++ Reference Captured in Block" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check flags when a C++ reference is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,i.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"- (void)ref_captured_in_escaping_block_bad:(int&)y {\n  dispatch_async(dispatch_get_main_queue(), ^{\n    int a = y;\n    ...\n  });\n  ...;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This could cause crashes because C++ references are not managed pointers\n(like ARC pointers) and so the referent is likely to be gone if the block\ndereferences it later."}),"\n",(0,i.jsx)(n.h2,{id:"cxx_string_captured_in_block",children:"CXX_STRING_CAPTURED_IN_BLOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "C++ String Captured in Block" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,i.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,i.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"  std::string fullName;\n  const char* c = fullName.c_str();\n  dispatch_async(dispatch_get_main_queue(), ^{\n    const char* c1 = c;\n  });\n"})}),"\n",(0,i.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,i.jsx)(n.h2,{id:"data_flow_to_sink",children:"DATA_FLOW_TO_SINK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Data Flow to Sink" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A flow of data was detected to a sink."}),"\n",(0,i.jsx)(n.h2,{id:"deadlock",children:"DEADLOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Deadlock" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This error is currently reported in Java. A deadlock occurs when two distinct\nthreads try to acquire two locks in reverse orders. The following code\nillustrates a textbook example. Of course, in real deadlocks, the lock\nacquisitions may be separated by deeply nested call chains."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  public void lockAThenB() {\n    synchronized(lockA) {\n      synchronized(lockB) {\n       // do something with both resources\n      }\n    }\n  }\n\n  public void lockBThenA() {\n    synchronized(lockB) {\n      synchronized(lockA) {\n       // do something with both resources\n      }\n    }\n  }\n"})}),"\n",(0,i.jsx)(n.p,{children:"The standard solution to a deadlock is to fix an order of lock acquisition and\nadhere to that order in all cases. Another solution may be to shrink the\ncritical sections (i.e., the code executing under lock) to the minimum required."}),"\n",(0,i.jsxs)(n.p,{children:["Old-style containers such as ",(0,i.jsx)(n.code,{children:"Vector"})," are synchronized on the object monitor,\nwhich means that deadlocks can occur even without explicit synchronisation on\nboth threads. For instance:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  public void lockAThenAddToVector() {\n    synchronized(lockA) {\n      vector.add(object);\n    }\n  }\n\n  public void lockVectorThenA() {\n    synchronized(vector) {\n      synchronized(lockA) {\n       // do s
1omething with both resources\n      }\n    }\n  }\n"})}),"\n",(0,i.jsx)(n.p,{children:"Infer has support for detecting these deadlocks too."}),"\n",(0,i.jsxs)(n.p,{children:["To suppress reports of deadlocks in a method ",(0,i.jsx)(n.code,{children:"m()"})," use the\n",(0,i.jsx)(n.code,{children:'@SuppressLint("DEADLOCK")'})," annotation, as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'  import android.annotation.SuppressLint;\n\n  @SuppressLint("DEADLOCK")\n  public void m() {\n  ...\n  }\n'})}),"\n",(0,i.jsx)(n.h2,{id:"dead_store",children:"DEAD_STORE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Dead Store" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-liveness",children:"liveness"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This error is reported in C++. It fires when the value assigned to a variables\nis never used (e.g., ",(0,i.jsx)(n.code,{children:"int i = 1; i = 2; return i;"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase",children:"EXECUTION_TIME_COMPLEXITY_INCREASE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of a\nprogram increases in degree: e.g. from constant to linear or from\nlogarithmic to quadratic. This issue type is only reported in\ndifferential mode: i.e when we are comparing the cost analysis results of\ntwo runs of infer on a file. Check out examples in ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost#examples-execution-cost",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase_ui_thread",children:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of the procedure increases in degree ",(0,i.jsx)(n.strong,{children:"and"})," the procedure runs on the UI (main) thread."]}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_unreachable_at_exit",children:"EXECUTION_TIME_UNREACHABLE_AT_EXIT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Execution Time Unreachable At Exit" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates that the program's execution doesn't reach\nthe exit node (where our analysis computes the final cost of the\nprocedure). Hence, we cannot compute a static bound for the procedure."}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void exit_unreachable() {\n  exit(0); // modeled as unreachable\n}\n\nvoid infeasible_path_unreachable() {\n    Preconditions.checkState(false); // like assert false, state pruned to bottom\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_execution_time",children:"EXPENSIVE_EXECUTION_TIME"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Expensive Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["[EXPERIMENTAL] This warning indicates that the procedure has non-constant and non-top execution cost. By default, this issue type is disabled. To enable it, set ",(0,i.jsx)(n.code,{children:"enabled=true"})," in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/base/costKind.ml#L55",children:"costKind.ml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For instance, a simple example where we report this issue is a function with linear cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int sum_linear(ArrayList<Integer> list){\n int sum = 0;\n for (Integer el: list){\n   sum += el;\n }\n return sum;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_loop_invariant_call",children:"EXPENSIVE_LOOP_INVARIANT_CALL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Expensive Loop Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["We report this issue type when a function is ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#invariant_call",children:"loop-invariant"})," and also expensive (i.e. at least has linear complexity as determined by the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"})," analysis)."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int incr(int x) {\
1n  return x + 1;\n}\n\n// incr will not be hoisted since it is cheap(constant time)\nvoid foo_linear(int size) {\n  int x = 10;\n  for (int i = 0; i < size; i++) {\n    incr(x); // constant call, don't hoist\n  }\n}\n\n// call to foo_linear will be hoisted since it is expensive(linear in size).\nvoid symbolic_expensive_hoist(int size) {\n  for (int i = 0; i < size; i++) {\n    foo_linear(size); // hoist\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"guardedby_violation",children:"GUARDEDBY_VIOLATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "GuardedBy Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A field annotated with ",(0,i.jsx)(n.code,{children:"@GuardedBy"})," is being accessed by a call-chain that starts at a non-private method without synchronization."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'class C {\n  @GuardedBy("this")\n  String f;\n\n  void foo(String s) {\n    f = s; // unprotected access here\n  }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Action: Protect the offending access by acquiring the lock indicated by the ",(0,i.jsx)(n.code,{children:"@GuardedBy(...)"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"impure_function",children:"IMPURE_FUNCTION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Impure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates impure functions. For instance, below functions would be marked as impure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void makeAllZero_impure(ArrayList<Foo> list) {\n  Iterator<Foo> listIterator = list.iterator();\n  while (listIterator.hasNext()) {\n    Foo foo = listIterator.next();\n    foo.x = 0;\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Inefficient Keyset Iterator" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"inefficient-keyset-iterator"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This issue is raised when"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["iterating over a HashMap with ",(0,i.jsx)(n.code,{children:"keySet()"})," iterator"]}),"\n",(0,i.jsx)(n.li,{children:"looking up the key each time"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void inefficient_loop_bad(HashMap<String, Integer> testMap) {\n for (String key : testMap.keySet()) {\n   Integer value = testMap.get(key); // extra look-up cost\n   foo(key, value);\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Instead, it is more efficient to iterate over the loop with ",(0,i.jsx)(n.code,{children:"entrySet"})," which returns key-vaue pairs and gets rid of the hashMap lookup."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void efficient_loop_ok(HashMap<String, Integer> testMap) {\n  for (Map.Entry<String, Integer> entry : testMap.entrySet()) {\n    String key = entry.getKey();\n    Integer value = entry.getValue();\n    foo(key, value);\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_big",children:"INFERBO_ALLOC_IS_BIG"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Alloc Is Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is passed a large constant value (>=10^6). For example, ",(0,i.jsx)(n.code,{children:"int n = 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument or make sure it is really needed."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_negative",children:"INFERBO_ALLOC_IS_NEGATIVE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Alloc Is Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a negative size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_zero",children:"INFERBO_ALLOC_IS_ZERO"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Alloc Is Zero" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a zero size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 3; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_ZERO"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_big",children:"INFERBO_ALLOC_MAY_BE_BIG"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Alloc May Be Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a large value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a boun
1d checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n < A_SMALL_NUMBER) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_negative",children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Alloc May Be Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a negative value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : -5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n > 0) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"infinite_execution_time",children:"INFINITE_EXECUTION_TIME"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Infinite Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This warning indicates that Infer was not able to determine a static\nupper bound on the execution cost of the procedure. By default, this\nissue type is disabled."}),"\n",(0,i.jsx)(n.h3,{id:"example-1-t-due-to-expressivity",children:"Example 1: T due to expressivity"}),"\n",(0,i.jsx)(n.p,{children:"For instance, Inferbo's interval analysis is limited to affine\nexpressions. Hence, we can't statically estimate an upper bound on the\nbelow example and obtain T(unknown) cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: square root(x), got T\nvoid square_root_FP(int x) {\n int i = 0;\n while (i * i < x) {\n   i++;\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"example-2-t-due-to-unmodeled-calls",children:"Example 2: T due to unmodeled calls"}),"\n",(0,i.jsx)(n.p,{children:"Another common case where we get T cost is when Infer cannot statically determine the range of values for loop bounds. For instance,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void loop_over_charArray_FP(StringBuilder builder, String input) {\n  for (Character c : input.toCharArray()) {}\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Here, Infer does not have any InferBo models for the range of values returned by ",(0,i.jsx)(n.code,{children:"String.toCharArray"}),", hence it cannot determine that we will be iterating over a char array in the size of ",(0,i.jsx)(n.code,{children:"input"})," string."]}),"\n",(0,i.jsxs)(n.p,{children:["To teach InferBo about such library calls, they should be semantically modeled in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/bufferoverrun/bufferOverrunModels.ml",children:"InferBo"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"example-3-t-due-to-calling-another-t-costed-function",children:"Example 3: T due to calling another T-costed function"}),"\n",(0,i.jsx)(n.p,{children:"Since the analysis is inter-procedural, another example we can have T cost is if at least one of the callees has T cost."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: constant, got T\nvoid call_top_cost_FP() {\n square_root_FP(1); // square_root_FP has Top cost\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"infinite_loop",children:"INFINITE_LOOP"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Infinite Loop" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"An infinite loop has been detected. The program won't terminate."}),"\n",(0,i.jsx)(n.p,{children:"Example of recursive function:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-C",children:"void loop(int x) {\n  int y = 1;\n  while (x != 3)\n    y++;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"infinite_recursion",children:"INFINITE_RECURSION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Infinite Recursion" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A special case of ",(0,i.jsx)(n.a,{href:"#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})," where we detected that the recursive call is made with the exact same values, which guarantees an infinite recursion."]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Integer Overflow L1" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when integer overflow occurred by integer operations such as addition, subtraction,\nand multiplication. For example, ",(0,i.jsx)(n.code,{children:"int n = INT_MAX; int m = n + 3;"})," generates a INTEGER_OVERFLOW_L1\non ",(0,i.jsx)(n.code,{children:"n + 3"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Integer overflows reports fall into several "buckets" corresponding to the expected precision of the\nreport. The higher the number, the more likely it is to be a false positive.'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,i.jsx)(n.em,{children:"must"})," be unsafe.  For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [1,1]"})," in 32-bit signed integer type."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,i.jsx)(n.code,{children:"L1"}),", when it ",(0,i.jsx)(n.em,{children:"may"})," be unsafe.  For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [0,1]"})," in 32-bit signed integer type.  Note that the integer of RHS\ncan be 0, which is safe."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L5"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"U5"}),": A binary integer operation is unsafe by unknown values, which are usually from unknown\nfunction calls."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l2",children:"INTEGER_OVERFLOW_L2"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Integer Overflow L2" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l5",children:"INTEGER_OVERFLOW_L5"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Integer Overflow L5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_u5",children:"INTEGER_OVERFLOW_U5"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Integer Overflow U5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Interface Not Thread Safe" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This error indicates that you have invoked an interface method not annotated\nwith ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," from a thread-safe context (e.g., code that uses locks or is\nmarked ",(0,i.jsx)(n.code,{children:"@ThreadSafe"}),"). The fix is to add the ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," annotation to the\ninterface or to the interface method. For background on why these annotations\nare needed, see the detailed explanation\n",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd#interface-not-thread-safe",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"invalid_sil",children:"INVALID_SIL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Invalid Sil" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-sil-validation",children:"sil-validation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"The SIL instruction does not conform to the expected subset of instructions\nexpected for the front-end of the language for the analyzed code."}),"\n",(0,i.jsx)(n.h2,{id:"invariant_call",children:"INVARIANT_CALL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"We report this issue type when a function call is loop-invariant and hoistable, i.e."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the function has no side side effects (pure)"}),"\n",(0,i.jsx)(n.li,{children:"has invariant arguments and result (i.e. have the same value in all loop iterations)"}),"\n",(0,i.jsx)(n.li,{children:"it is guaranteed to execute, i.e. it dominates all loop sources"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int foo(int x, int y) {\n return x + y;\n}\n\n\nvoid invariant_hoist(int size) {\n    int x = 10;\n    int y = 5;\n    for (int i = 0; i < size;
1 i++) {\n      foo(x, y); // hoistable\n    }\n  }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Ipc On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A blocking ",(0,i.jsx)(n.code,{children:"Binder"})," IPC call occurs on the UI thread."]}),"\n",(0,i.jsx)(n.h2,{id:"lab_resource_leak",children:"LAB_RESOURCE_LEAK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Lab Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-resource-leak-lab",children:"resource-leak-lab"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Toy issue."}),"\n",(0,i.jsx)(n.h2,{id:"lineage_flow",children:"LINEAGE_FLOW"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Lineage Flow" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-lineage",children:"lineage"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A Lineage taint flow has been detected from a source to a sink."}),"\n",(0,i.jsx)(n.h2,{id:"lockless_violation",children:"LOCKLESS_VIOLATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Lockless Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A method implements an interface signature annotated with ",(0,i.jsx)(n.code,{children:"@Lockless"})," but which transitively acquires a lock."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"Interface I {\n    @Lockless\n    public void no_lock();\n}\n\nclass C implements I {\n  private synchronized do_lock() {}\n\n  public void no_lock() { // this method should not acquire any locks\n    do_lock();\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Lock Consistency Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This is an error reported on C++ and Objective C classes whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Some class method directly uses locking primitives (not transitively)."}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which writes to some member ",(0,i.jsx)(n.code,{children:"x"})," while holding a lock."]}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which reads ",(0,i.jsx)(n.code,{children:"x"})," without holding a lock."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The above may happen through a chain of calls. Above, ",(0,i.jsx)(n.code,{children:"x"})," may also be a\ncontainer (an array, a vector, etc)."]}),"\n",(0,i.jsx)(n.h3,{id:"fixing-lock-consistency-violation-reports",children:"Fixing Lock Consistency Violation reports"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Avoid the offending access (most often the read). Of course, this may not be\npossible."}),"\n",(0,i.jsx)(n.li,{children:"Use synchronization to protect the read, by using the same lock protecting the\ncorresponding write."}),"\n",(0,i.jsx)(n.li,{children:"Make the method doing the read access private. This should silence the\nwarning, since Infer looks for a pair of non-private methods. Objective-C:\nInfer considers a method as private if it's not exported in the header-file\ninterface."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"lock_on_ui_thread",children:"LOCK_ON_UI_THREAD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Lock on UI Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A method annoted as being on UIThread acquires a lock. This could be a potential performance issue"}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class Example {\n    @UiThread\n    void foo() {\n        synchronized(this) {\n        }\n    }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_c",children:"MEMORY_LEAK_C"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-c",children:"Memory leak in C"}),"\n",(0,i.jsx)(n.p,{children:"This error type is only reported in C and Objective-C code. In Java we do not\nreport memory leaks because it is a garbage collected language."}),"\n",(0,i.jsxs)(n.p,{children:["In C, Infer reports memory leaks when objects are created with ",(0,i.jsx)(n.code,{children:"malloc"}
1)," and not\nfreed. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"-(void) memory_leak_bug {\n    struct Person *p = malloc(sizeof(struct Person));\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-objective-c",children:"Memory leak in Objective-C"}),"\n",(0,i.jsx)(n.p,{children:"Additionally, in Objective-C, Infer reports memory leaks that happen when\nobjects from Core Foundation or Core Graphics don't get released."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) memory_leak_bug_cf {\n    CGPathRef shadowPath = CGPathCreateWithRect(self.inputView.bounds, NULL); //object created and not released.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_cpp",children:"MEMORY_LEAK_CPP"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"})]}),"\n",(0,i.jsx)(n.h2,{id:"missing_nullability_annotation",children:"MISSING_NULLABILITY_ANNOTATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Missing Nullability Annotation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-swift-objc-nullability",children:"swift-objc-nullability"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["An Objective-C method that returns a pointer is being called from Swift,\nbut its declaration carries no nullability annotation (",(0,i.jsx)(n.code,{children:"_Nullable"})," or\n",(0,i.jsx)(n.code,{children:"_Nonnull"}),"). Without an annotation Swift's clang importer treats the result\nas an Implicitly Unwrapped Optional (",(0,i.jsx)(n.code,{children:"T!"}),"), so any subsequent use that\nassumes non-nil values traps at runtime if the method ever returns ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"why-this-matters",children:"Why this matters"}),"\n",(0,i.jsx)(n.p,{children:'Objective-C uses raw pointers and signals "may be nil" only by convention.\nSwift, by contrast, requires nullability to be explicit in the type system:'}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Objective-C declaration"}),(0,i.jsx)(n.th,{children:"Swift import"}),(0,i.jsxs)(n.th,{children:["Behaviour on ",(0,i.jsx)(n.code,{children:"nil"})]})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString *)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String!"})}),(0,i.jsxs)(n.td,{children:["implicit unwrap, ",(0,i.jsx)(n.strong,{children:"trap"})]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString * _Nonnull)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String"})}),(0,i.jsx)(n.td,{children:"impossible by contract"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString * _Nullable)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String?"})}),(0,i.jsx)(n.td,{children:"safe; caller must unwrap"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["The unannotated form is the dangerous one: Swift will silently let you\nwrite ",(0,i.jsx)(n.code,{children:"api.foo().count"})," even though the underlying call may return ",(0,i.jsx)(n.code,{children:"nil"}),",\nand the trap fires far away from the missing annotation."]}),"\n",(0,i.jsx)(n.h3,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"// LegacyAPI.h - third-party header, no annotation\n@interface LegacyAPI : NSObject\n- (NSString *)getOptionalThing;\n@end\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func bad(api: LegacyAPI) {\n  let s = api.getOptionalThing()  // imported as String!\n  print(s.count)                  // crashes if getOptionalThing returns nil\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports ",(0,i.jsx)(n.code,{children:"MISSING_NULLABILITY_ANNOTATION"})," on the call to\n",(0,i.jsx)(n.code,{children:"getOptionalThing"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"preferred-fix-annotate-the-objective-c-header",children:"Preferred fix: annotate the Objective-C header"}),"\n",(0,i.jsxs)(n.p,{children:["Edit the declaration to state the contract explicitly. If the method may\nreturn ",(0,i.jsx)(n.code,{children:"nil"}),", mark it ",(0,i.jsx)(n.code,{children:"_Nullable"}),"; otherwise mark it ",(0,i.jsx)(n.code,{children:"_Nonnull"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"// LegacyAPI.h\n@interface LegacyAPI : NSObject\n- (NSString * _Nullable)getOptionalThing;\n@end\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now Swift imports the result as ",(0,i.jsx)(n.code,{children:"String?"})," and the compiler forces the\ncaller to handle the nil case:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func good(api: LegacyAPI) {\n  if let s = api.getOptionalThing() {\n    print(s.count)\n  }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["For headers that already wrap whole regions in\n",(0,i.jsx)(n.code,{children:"NS_ASSUME_NONNULL_BEGIN"})," / ",(0,i.jsx)(n.code,{children:"NS_ASSUME_NONNULL_END"}),", only the exception\nneeds the explicit ",(0,i.jsx)(n.code,{children:"_Nullable"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"workaround-when-you-cannot-edit-the-header",children:"Workaround when you cannot edit the header"}),"\n",(0,i.jsxs)(n.p,{children:["If the declaration lives in a third-party framework or a header you do not\nown, defend at the Swift call site by casting the result to an Optional\nwith ",(0,i.jsx)(n.code,{children:"as?"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func goodWorkaround(api: LegacyAPI) {\n  if let s = api.getOptionalThing() as? NSString {\n    print(s.length)\n  }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"as?"})," cast lifts the IUO into a real ",(0,i.jsx)(n.code,{children:"Optional"}),", and ",(0,i.jsx)(n.code,{children:"if let"})," /\n",(0,i.jsx)(n.code,{children:"guard let"})," then forces the nil case to be handled. Infer recognises this\ndefensive shape (an ",(0,i.jsx)(n.code,{children:"objc_msgSend"})," whose result feeds a\n",(0,i.jsx)(n.code,{children:"_bridgeToObjectiveC"})," call in the lowered IR) and stops reporting on the\ncall."]}),"\n",(0,i.jsxs)(n.p,{children:["A bare force-unwrap (",(0,i.jsx)(n.code,{children:"api.getOptionalThing()!"}),") is ",(0,i.jsx)(n.strong,{children:"not"})," a fix: it makes\nthe trap explicit but does not eliminate it, and infer will c
1ontinue to\nreport on the call."]}),"\n",(0,i.jsx)(n.h2,{id:"missing_nullability_annotation_pulse",children:"MISSING_NULLABILITY_ANNOTATION_PULSE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Missing Nullability Annotation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["An Objective-C method that returns a pointer is being called from Swift,\nbut its declaration carries no nullability annotation (",(0,i.jsx)(n.code,{children:"_Nullable"})," or\n",(0,i.jsx)(n.code,{children:"_Nonnull"}),"). Without an annotation Swift's clang importer treats the result\nas an Implicitly Unwrapped Optional (",(0,i.jsx)(n.code,{children:"T!"}),"), so any subsequent use that\nassumes non-nil values traps at runtime if the method ever returns ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"why-this-matters-1",children:"Why this matters"}),"\n",(0,i.jsx)(n.p,{children:'Objective-C uses raw pointers and signals "may be nil" only by convention.\nSwift, by contrast, requires nullability to be explicit in the type system:'}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Objective-C declaration"}),(0,i.jsx)(n.th,{children:"Swift import"}),(0,i.jsxs)(n.th,{children:["Behaviour on ",(0,i.jsx)(n.code,{children:"nil"})]})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString *)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String!"})}),(0,i.jsxs)(n.td,{children:["implicit unwrap, ",(0,i.jsx)(n.strong,{children:"trap"})]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString * _Nonnull)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String"})}),(0,i.jsx)(n.td,{children:"impossible by contract"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"- (NSString * _Nullable)foo;"})}),(0,i.jsx)(n.td,{children:(0,i.jsx)(n.code,{children:"func foo() -> String?"})}),(0,i.jsx)(n.td,{children:"safe; caller must unwrap"})]})]})]}),"\n",(0,i.jsxs)(n.p,{children:["The unannotated form is the dangerous one: Swift will silently let you\nwrite ",(0,i.jsx)(n.code,{children:"api.foo().count"})," even though the underlying call may return ",(0,i.jsx)(n.code,{children:"nil"}),",\nand the trap fires far away from the missing annotation."]}),"\n",(0,i.jsx)(n.h3,{id:"example-1",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"// LegacyAPI.h - third-party header, no annotation\n@interface LegacyAPI : NSObject\n- (NSString *)getOptionalThing;\n@end\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func bad(api: LegacyAPI) {\n  let s = api.getOptionalThing()  // imported as String!\n  print(s.count)                  // crashes if getOptionalThing returns nil\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports ",(0,i.jsx)(n.code,{children:"MISSING_NULLABILITY_ANNOTATION"})," on the call to\n",(0,i.jsx)(n.code,{children:"getOptionalThing"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"preferred-fix-annotate-the-objective-c-header-1",children:"Preferred fix: annotate the Objective-C header"}),"\n",(0,i.jsxs)(n.p,{children:["Edit the declaration to state the contract explicitly. If the method may\nreturn ",(0,i.jsx)(n.code,{children:"nil"}),", mark it ",(0,i.jsx)(n.code,{children:"_Nullable"}),"; otherwise mark it ",(0,i.jsx)(n.code,{children:"_Nonnull"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"// LegacyAPI.h\n@interface LegacyAPI : NSObject\n- (NSString * _Nullable)getOptionalThing;\n@end\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Now Swift imports the result as ",(0,i.jsx)(n.code,{children:"String?"})," and the compiler forces the\ncaller to handle the nil case:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func good(api: LegacyAPI) {\n  if let s = api.getOptionalThing() {\n    print(s.count)\n  }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["For headers that already wrap whole regions in\n",(0,i.jsx)(n.code,{children:"NS_ASSUME_NONNULL_BEGIN"})," / ",(0,i.jsx)(n.code,{children:"NS_ASSUME_NONNULL_END"}),", only the exception\nneeds the explicit ",(0,i.jsx)(n.code,{children:"_Nullable"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"workaround-when-you-cannot-edit-the-header-1",children:"Workaround when you cannot edit the header"}),"\n",(0,i.jsxs)(n.p,{children:["If the declaration lives in a third-party framework or a header you do not\nown, defend at the Swift call site by casting the result to an Optional\nwith ",(0,i.jsx)(n.code,{children:"as?"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func goodWorkaround(api: LegacyAPI) {\n  if let s = api.getOptionalThing() as? NSString {\n    print(s.length)\n  }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"as?"})," cast lifts the IUO into a real ",(0,i.jsx)(n.code,{children:"Optional"}),", and ",(0,i.jsx)(n.code,{children:"if let"})," /\n",(0,i.jsx)(n.code,{children:"guard let"})," then forces the nil case to be handled. Infer recognises this\ndefensive shape (an ",(0,i.jsx)(n.code,{children:"objc_msgSend"})," whose result feeds a\n",(0,i.jsx)(n.code,{children:"_bridgeToObjectiveC"})," call in the lowered IR) and stops reporting on the\ncall."]}),"\n",(0,i.jsxs)(n.p,{children:["A bare force-unwrap (",(0,i.jsx)(n.code,{children:"api.getOptionalThing()!"}),") is ",(0,i.jsx)(n.strong,{children:"not"})," a fix: it makes\nthe trap explicit but does not eliminate it, and infer will c
1ontinue to\nreport on the call."]}),"\n",(0,i.jsx)(n.h2,{id:"missing_required_prop",children:"MISSING_REQUIRED_PROP"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Missing Required Prop" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-litho-required-props",children:"litho-required-props"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issues is reported when a required ",(0,i.jsx)(n.code,{children:"@Prop"})," is missing."]}),"\n",(0,i.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,i.jsxs)(n.p,{children:["Assume that the following Litho Component specification is defined as follows where ",(0,i.jsx)(n.code,{children:"prop1"})," is optional and ",(0,i.jsx)(n.code,{children:"prop2"})," is required."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n  static void onCreate(\n      ComponentContext c,\n      @Prop(optional = true) String prop1, @Prop int prop2) {\n    ...\n  }\n  ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["When we build the corresponding component, we should have all the required props. If we are missing optional props (e..g ",(0,i.jsx)(n.code,{children:"prop1"})," below), it is ok."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"MyComponent.create(c)\n    .prop2(8)\n    .build();\n"})}),"\n",(0,i.jsxs)(n.p,{children:["However, if we are missing a required prop, Infer gives an error below for the missing ",(0,i.jsx)(n.code,{children:"prop2"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n    .prop1("My prop 1")\n    .build();\n'})}),"\n",(0,i.jsx)(n.p,{children:"** Action **"}),"\n",(0,i.jsx)(n.p,{children:"There are two ways to fix this issue."}),"\n",(0,i.jsxs)(n.p,{children:["First, we could add the missing ",(0,i.jsx)(n.code,{children:"prop2"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n    .prop1("My prop 1")\n    .prop2(x) // where x is some integer\n    .build();\n'})}),"\n",(0,i.jsxs)(n.p,{children:["or alternatively, if the ",(0,i.jsx)(n.code,{children:"prop2"})," is not really required, we could change the component spec to reflect that:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n  static void onCreate(\n      ComponentContext c,\n      @Prop(optional = true) String prop1, @Prop(optional = true) int prop2) {\n    ...\n  }\n  ...\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Mixed Self WeakSelf" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check reports an issue when an Objective-C block captures both ",(0,i.jsx)(n.code,{children:"self"})," and ",(0,i.jsx)(n.code,{children:"weakSelf"}),", a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),".\nPossibly the developer meant to capture only ",(0,i.jsx)(n.code,{children:"weakSelf"})," to avoid a retain cycle, but made a typo and used ",(0,i.jsx)(n.code,{children:"self"}),"\ninstead of ",(0,i.jsx)(n.code,{children:"strongSelf"}),". In this case, this could cause a retain cycle."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    if (strongSelf) {\n      [strongSelf foo];\n      int x = self->x; // typo here\n    }\n    return 0;\n  };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),": Fixing the typo is generally the right course of action."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"}
1)," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"modifies_immutable",children:"MODIFIES_IMMUTABLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Modifies Immutable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue type indicates modifications to fields marked as @Immutable. For instance, below function ",(0,i.jsx)(n.code,{children:"mutateArray"})," would be marked as modifying immutable field ",(0,i.jsx)(n.code,{children:"testArray"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  @Immutable int[] testArray = new int[]{0, 1, 2, 4};\n  \n  int[] getTestArray() {\n    return testArray;\n  }                \n          \n  void mutateArray() {\n    int[] array = getTestArray();\n    array[2] = 7;\n  }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"multiple_weakself",children:"MULTIPLE_WEAKSELF"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Multiple WeakSelf Use" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when an Objective-C block uses ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),") more than once.\nThis could lead to unexpected behaviour. Even if ",(0,i.jsx)(n.code,{children:"weakSelf"})," is not nil in the first use, it could be nil\nin the following uses since the object that ",(0,i.jsx)(n.code,{children:"weakSelf"})," points to could be freed anytime."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n      [weakSelf foo];\n      int x = weakSelf->x;\n  };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nOne should assign ",(0,i.jsx)(n.code,{children:"weakSelf"})," to a strong pointer first, and then\nuse it in the block."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    if (strongSelf) {\n      [strongSelf foo];\n      int x = strongSelf->x;\n    }\n    ...\n  };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Mutual Recursion Cycle" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A recursive call or mutually recursive call has been detected. This does ",(0,i.jsx)(n.em,{children:"not"})," mean that the program won't terminate, just that the code is recursive. You should double-check if the recursion is intended and if it can lead to non-termination or a stack overflow."]}),"\n",(0,i.jsx)(n.p,{children:"Example of recursive function:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-C",children:"int factorial(int x) {\n  if (x > 0) {\n    return x * factorial(x-1);\n  } else {\n    return 1;\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call",children:"NIL_BLOCK_CALL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when one tries to call an Objective-C block that is ",(0,i.jsx)(n.code,{children:"nil"}),".\nThis causes a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) foo:(void (^)())callback {\n    callback();\n}\n\n-(void) bar {\n    [self foo:nil]; //crash\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling the block, or making sure never to call the method ",(0,i.jsx)(n.code,{children:"foo:"})," with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_block_call",children:"NIL_BLOCK_CALL"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports when ",(0,i.jsx)(n.code,{children:"nil"})," is passed to collections in Objective-C such as arrays and dictionaries. This causes a crash."]}),"\n",(0,i.jsx)(n.h3,{id:"arrays",children:"Arrays"}),"\n",(0,i.jsxs)(n.p,{children:["Adding objects to an array, inserting objects at a given index, or replacing objects at a given index, can all\nlead to a crash when the object is ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  [mArray addObject:nil];  //crash\n\n  [mArray insertObject:nil atIndex:0];   //crash\n\n  [mArray replaceObjectAtIndex:0 withObject:nil]; //crash\n"})}),"\n",(0,i.jsx)(n.h3,{id:"dictionaries",children:"Dictionaries"}),"\n",(0,i.jsxs)(n.p,{children:["Adding a ",(0,i.jsx)(n.code,{children:"nil"})," value in a dictionary causes a crash. If the concept of ",(0,i.jsx)(n.code,{children:"nil"})," is required, one can add\n",(0,i.jsx)(n.code,{children:"[NSNull null]"})," instead."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:'  id value = nil;
1\n  [mDict setObject:value forKey:@"somestring"]; //crash\n\n  [mDict setObject:[NSNull null] forKey:@"somestring"]; //ok\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Retrieving or removing an object from a dictionary with a ",(0,i.jsx)(n.code,{children:"nil"})," key also causes a crash:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:'    id key = nil;\n    mDict[key] = @"somestring"; //crash\n\n   [mDict removeObjectForKey:nil]; //crash\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["In all the cases above, when passing ",(0,i.jsx)(n.code,{children:"nil"})," causes a crash, the solutions are either making sure\nthat the object passed will never be ",(0,i.jsx)(n.code,{children:"nil"}),", or adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling those methods."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, calling a method on ",(0,i.jsx)(n.code,{children:"nil"})," (or in Objective-C terms, sending a message to ",(0,i.jsx)(n.code,{children:"nil"}),") does not crash,\nit simply returns a falsy value (nil/0/false). However, sending a message that returns\na non-POD C++ type (POD being ",(0,i.jsx)(n.a,{href:"https://en.cppreference.com/w/cpp/named_req/PODType",children:'"Plain Old Data"'}),", essentially\nanything that cannot be compiled as a C-style struct) to ",(0,i.jsx)(n.code,{children:"nil"})," causes undefined behaviour."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr<int> callMethodReturnsnonPOD() {\n  SomeObject* obj = getObjectOrNil();\n  std::shared_ptr<int> d = [obj returnsnonPOD]; // UB\n  return d;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["To fix the above issue, we need to check if ",(0,i.jsx)(n.code,{children:"obj"})," is\nnot ",(0,i.jsx)(n.code,{children:"nil"})," before calling the ",(0,i.jsx)(n.code,{children:"returnsnonPOD"})," method:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr<int> callMethodReturnsnonPOD(bool b) {\n  SomeObject* obj = getObjectOrNil(b);\n  if (obj == nil) { return std::make_shared<int>(0); }\n  std::shared_ptr<int> d = [obj returnsnonPOD];\n  return d;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No matching branch is found when evaluating the ",(0,i.jsx)(n.code,{children:"of"})," section of a ",(0,i.jsx)(n.code,{children:"try"})," expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{try_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n    try X of\n        [_|T] -> {ok,T}\n    catch\n        _ -> error\n    end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No matching case clause in Erlang: Reports an error when none of the clauses of a ",(0,i.jsx)(n.code,{children:"case"})," match the expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{case_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n    case X of\n        [_|T] -> T\n    end.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No matching else clause in Erlang: Reports an error when none of the clauses of an ",(0,i.jsx)(n.code,{children:"else"}
1)," match the short-circuit result from ",(0,i.jsx)(n.code,{children:"maybe"})," body. Corresponds to the ",(0,i.jsx)(n.code,{children:"{else_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, here the ",(0,i.jsx)(n.code,{children:"1 ?= 2"})," expression does not match and short-circuits to ",(0,i.jsx)(n.code,{children:"2"}),", which does not match the single clause under ",(0,i.jsx)(n.code,{children:"else"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"else_clause_error() ->\n    maybe\n        1 ?= 2\n    else\n        1 -> ok\n    end.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No matching function clause in Erlang: Reports an error when none of the clauses of a function match the arguments of a call. Corresponds to the ",(0,i.jsx)(n.code,{children:"function_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail([_|Xs]) -> Xs.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No match of right hand side value in Erlang: Reports an error when the right hand side value of a ",(0,i.jsx)(n.code,{children:"match"})," expression does not match the pattern on the left hand side. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badmatch,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, ",(0,i.jsx)(n.code,{children:"[H|T] = []"})," gives the error because the left hand side pattern requires at least one element in the list on the right hand side."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["No true branch when evaluating an if expression in Erlang: Reports an error when none of the branches of an ",(0,i.jsx)(n.code,{children:"if"})," expression evaluate to true. Corresponds to the ",(0,i.jsx)(n.code,{children:"if_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"sign(0)"})," and the full definition of ",(0,i.jsx)(n.code,{children:"sign"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"sign(X) ->\n    if\n        X > 0 -> positive;\n        X < 0 -> negative\n    end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nsstring_internal_ptr_captured_in_block",children:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}
1),'. Reported as "NSString Captured in Block" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,i.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,i.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"  std::string fullName;\n  const char* c = fullName.c_str();\n  dispatch_async(dispatch_get_main_queue(), ^{\n    const char* c1 = c;\n  });\n"})}),"\n",(0,i.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  p = foo(); // foo() might return null\n  stuff();\n  p.goo();   // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n  //... intervening code\n\n  p = checkNotNull(foo()); // foo() might return null\n  stuff();\n  p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n  int age;\n  int height;\n  int weight;\n};\nint get_age(struct Person *who) {\n  return who->age;\n}
1\nint null_pointer_interproc() {\n  struct Person *joe = 0;\n  return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param {  // passing nil\n  D* d = [param bar];   // nil message passing\n  return d->fld;        // crash\n}\n(void) callFoo {\n  C* c = [self bar];    // returns nil\n  [foo:c];              // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java-1",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  p = foo(); // foo() might return null\n  stuff();\n  p.goo();   // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n  //... intervening code\n\n  p = checkNotNull(foo()); // foo() might return null\n  stuff();\n  p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}
1),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c-1",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n  int age;\n  int height;\n  int weight;\n};\nint get_age(struct Person *who) {\n  return who->age;\n}\nint null_pointer_interproc() {\n  struct Person *joe = 0;\n  return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c-1",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param {  // passing nil\n  D* d = [param bar];   // nil message passing\n  return d->fld;        // crash\n}\n(void) callFoo {\n  C* c = [self bar];    // returns nil\n  [foo:c];              // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"null_argument",children:"NULL_ARGUMENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"This issue type indicates `nil` being passed as argument where a non-nil value expected.\n\n#import <Foundation/Foundation.h>\n\n// Test (non-nil) returned values of NSString methods against `nil`\nNSString* stringNotNil(NSString* str) {\n  if (!str) {\n        // ERROR: NSString:stringWithString: expects a non-nil value\n\treturn [NSString stringWithString:nil];\n  }\n  return str;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"null_argument_latent",children:"NULL_ARGUMENT_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#null_argument",children:"NULL_ARGUMENT"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Optional Empty Access warnings are reported when we try to retrieve the value of a ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/folly/blob/master/folly/Optional.h",children:(0,i.jsx)(n.code,{children:"folly::Optional"})})," when it is empty (i.e. ",(0,i.jsx)(n.code,{children:"folly::none"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:["In the following example we get a warning as ",(0,i.jsx)(n.code,{children:"int_opt"})," might be ",(0,i.jsx)(n.code,{children:"folly::none"})," and its value is being accessed:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v);\n\nfolly::Optional<int> mightReturnNone(int v) {\n   if (somef(v)) {\n      return folly::Optional(v);\n   }\n\n   return folly::none;\n}\n\nint value_no_check() {\n  folly::Optional<int> int_opt = mightReturnNone (4);\n  return int_opt.value(); // Optional Empty Access warning\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["We do not get the warning anymore if we add a check whether ",(0,i.jsx)(n.code,{children:"int_opt"})," is not empty:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"int value_check() {\n  folly::Optional<int> int_opt = mightReturnNone (4);\n  if (int_opt.has_value()) {\n     return int_opt.value(); // OK\n  }\n  return -1;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"In some cases we know that we have a non-empty value and there is no need to have a check. Consider the following example where Infer does not warn:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v) {return v > 3;};\n\nfolly::Optional<int> mightReturnNone(int v) {\n   if (somef(v)) {\n      return folly::Optional(v);\n   }\n\n   return folly::none;\n}\n\nint value_no_check() {\n  folly::Optional<int> int_opt = mightReturnNone (4); // cannot be folly::none\n  return int_opt.value(); // OK\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_assertion_error",children:"PULSE_ASSERTION_ERROR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Assertion Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported in Java and in Python. It fires when we detect a path that leads to an assertion failure."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Cannot Instantiate Abstract Class" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Instantiating an abstract class will lead to ",(0,i.jsx)(n.code,{children:"Cannot instantiate abstract class"})," error."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"abstract class AbstractClass1 {}\n\nclass ConcreteClass1 extends AbstractClass1 {}\n\npublic static function makeGeneric<T>(classname<T> $cls): void {\n    new $cls();\n}
1\n\n<<__ConsistentConstruct>>\nabstract class AbstractClass2 {\n\n  public static function makeStatic(): void {\n    new static();\n  }\n}\n\nclass ConcreteClass2 extends AbstractClass2 {}\n\npublic function badViaGeneric(): void {\n    Main::makeGeneric(AbstractClass1::class); // ERROR!\n}\n\npublic function goodViaGeneric(): void {\n  Main::makeGeneric(ConcreteClass1::class);\n}\n\npublic function badViaStatic(): void {\n  AbstractClass2::makeStatic(); // ERROR!\n}\n\npublic function goodViaStatic(): void {\n  ConcreteClass2::makeStatic();\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_const_refable",children:"PULSE_CONST_REFABLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Const Refable Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a function parameter is a) passed by value and b) is not modified inside the function. Instead, parameter can be passed by const reference, i.e. converted to a ",(0,i.jsx)(n.code,{children:"const&"})," so that no unnecessary copy is created at the callsite of the function."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include <vector>\n\nint read_first(const std::vector<int>& vec) { return vec[0]; }\n\nvoid const_refable(std::vector<int> vec) {\n  int first = read_first(vec); // vec is never modified, so the parameter should have type const&\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dict Missing Key" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,i.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to warn\nreading a missing key of dictionary in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the dictionary ",(0,i.jsx)(n.code,{children:"$d"})," has no entry for ",(0,i.jsx)(n.code,{children:"bye"}),", so reading\n",(0,i.jsx)(n.code,{children:"$d['bye']"})," will throw the ",(0,i.jsx)(n.code,{children:"OutOfBoundsException"})," exception, which is usually unexpected from\ndevelopers.  We can use a safer function ",(0,i.jsx)(n.code,{children:"idx"})," instead when keys of a dictionary is unclear."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"function simple_bad() : int {\n  $d = dict['hi' => 42, 'hello' => 52];\n  return $d['bye'];\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dynamic Type Mismatch" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported in Hack. It fires when we detect an operation that is incompatible\nwith the dynamic type of its arguments."}),"\n",(0,i.jsxs)(n.p,{children:["For example, reading ",(0,i.jsx)(n.code,{children:"$x['key']"})," when ",(0,i.jsx)(n.code,{children:"$x"})," is a vector."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Read-only Shared Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a shared pointer parameter is a) passed by value and b) is used only for reading, rather than lifetime extension. At the callsite, this might cause a potentially expensive unnecessary copy of the shared pointer, especially when many number of threads are sharing it. To avoid this, c
1onsider 1) passing the raw pointer instead and 2) use ",(0,i.jsx)(n.code,{children:"std::shared_ptr::get"})," at callsites."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(std::shared_ptr<T> x) {\n  // read_T(*x);\n}\n\nvoid caller() {\n  callee(shared_ptr);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"can be changed to"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(T* p) {\n  // read_T(*p);\n}\n\nvoid caller() {\n  callee(shared_ptr.get());\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Reference Stability" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["The family of maps ",(0,i.jsx)(n.code,{children:"folly::F14ValueMap"}),", ",(0,i.jsx)(n.code,{children:"folly::F14VectorMap"}),", and by extension\n",(0,i.jsx)(n.code,{children:"folly::F14FastMap"})," differs slightly from ",(0,i.jsx)(n.code,{children:"std::unordered_map"})," as it does not\nprovide reference stability. When the map resizes such as when ",(0,i.jsx)(n.code,{children:"reserve"})," is\ncalled or new elements are added, all existing references become invalid and\nshould not be used."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"operator[]"})," is an interesting case as it can easily introduce unsafe code when\nused twice in the same expression. Depending on what keys are present and which\norder the compiler sequences sub-expressions, an insert via ",(0,i.jsx)(n.code,{children:"operator[]"})," can\ninvalidate a reference obtained in the same expression before it's read from.\nTypically, those cases can be improved by using other map functions such as\n",(0,i.jsx)(n.code,{children:"at"}),", ",(0,i.jsx)(n.code,{children:"find"}),", ",(0,i.jsx)(n.code,{children:"emplace"}),", or ",(0,i.jsx)(n.code,{children:"insert_or_assign"})," to increase code quality and\nsafety."]}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include <folly/container/F14Map.h>\n\nvoid use_reference_after_growth_bad(folly::F14FastMap<int, int>& map) {\n  const auto& valueRef = map.at(1);\n  map.emplace(13, 71);\n  const auto valueCopy = valueRef;\n}\n\nvoid unsafe_expressions_bad(folly::F14FastMap<int, int>& map) {\n  // Unsafe expressions in situations where one or both keys are not present.\n  map[13] = map[71];\n  const auto p = map[13] * map[71];\n  const auto q = f(map[13], map[71]);\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#resource_leak",children:"RESOURCE_LEAK"})]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Transitive Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This issue tracks spurious accesses that are reachable from specific entry functions."}),"\n",(0,i.jsx)(n.p,{children:"Spurious accesses are specified as specific load/calls."}),"\n",(0,i.jsx)(n.p,{children:"Entry functions are specified through their enclosing class that must extend a specific\nclass and should not extend a list of specific classes."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unawaited Awaitable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Awaitable"})," values created by calls to asynchronous methods should eventually be ",(0,i.jsx)(n.code,{children:"await"}),"ed along all codepaths (even if their value is unused). Hence the following is ",(0,i.jsx)(n.em,{children:"not"})," OK"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"class A {\n  public static async genInt() : Awaitable<int>{\n    // typically do something involving IO\n  }\n\n  public static async genBad() : Awaitable<void> {\n    $_unused = self::genInt(); // ERROR: should have done $_unused = await self::genInt();\n    return;\n  }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Failure to ",(0,i.jsx)(n.code,{children:"await"})," an ",(0,i.jsx)(n.code,{children:"Awaitable"})," can lead to non-deterministic amount of the asynchronous call actually being executed, and can also indicate a logical confusion between ",(0,i.jsx)(n.code,{children:"T"})," and ",(0,i.jsx)(n.code,{children:"Awaitable<T>"})," that may not be caught by the type-checker."]}
1),"\n",(0,i.jsx)(n.h2,{id:"pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unfinished Builder" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Classes adhering to builder pattern are usually expected to call a finalizer function at some point to produce final result based on values that were passed to a builder itself. If finalizer function hasn't been called then builder's data won't be consumed in any meaningful way and will just be discarded."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"class MyBuilder {\n  private int $a = 0;\n  private int $b = 0;\n\n  public function setA(int $a): MyBuilder {\n    $this->a = $a;\n    return $this;\n  }\n\n  public function setB(int $b): MyBuilder {\n    $this->b = $b;\n    return $this;\n  }\n\n  public function saveX(): Awaitable<void> {\n    // typically do something involving IO\n  }\n}\n\nclass BuilderTester {\n  public static function builderUserOK(): void {\n    $b = new MyBuilder(0);\n    $b->setA(42)->setB(97)->saveX();\n  }\n\n  public static function builderUserBad(): void {\n    $b = new MyBuilder(0);\n    $b->setA(42)->setB(97); // ERROR: saveX hasn't been called so the builder's data is discarded\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,i.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to detect the uninitialized abstract const value in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the ",(0,i.jsx)(n.code,{children:"FIELD"})," can be read by the static method ",(0,i.jsx)(n.code,{children:"get_field"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["It is problematic invoking ",(0,i.jsx)(n.code,{children:"static::FIELD"}),", since it may be resolved to a ",(0,i.jsx)(n.code,{children:"A::FIELD"})," access, if called from ",(0,i.jsx)(n.code,{children:"A::get_field()"}),". Because ",(0,i.jsx)(n.code,{children:"FIELD"})," is abstract in ",(0,i.jsx)(n.code,{children:"A"}),", it is never assigned a value and the vm will crash. Unfortunately, Hack's type system cannot catch this."]}),"\n",(0,i.jsxs)(n.li,{children:["In the ",(0,i.jsx)(n.code,{children:"B"})," class, ",(0,i.jsx)(n.code,{children:"FIELD"})," is initialized, thus invoking ",(0,i.jsx)(n.code,{children:"B::get_field"})," is safe."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:'abstract class A {\n  abstract const string FIELD;\n  \n  public static function get_field(): string {\n    return static::FIELD;\n  }\n}\n\nfunction call_get_field_bad(): string {\n  return A::get_field();\n}\n\nclass B extends A {\n  const string FIELD = "defined";\n}\n\nfunction call_get_field_ok(): string {\n  return B::get_field();\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Method" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsx)(n.a,{href:"#pulse_uninitialized_const",children:(0,i.jsx)(n.code,{children:"PULSE_UNINITIALIZED_CONST"})}),", but it is to detect the uninitialized method call in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the static method ",(0,i.jsx)(n.code,{children:"foo"})," is declared only in the interface and the abstract class.  Thus, calling the static method can introduce an unexpected exception or a fatal error, while the type checker does miss the issue."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"interface MyInterface {\n  public static function foo(): string;\n}\n\nabstract class MyAbstractClass {\n  public abstract static function foo(): string;\n}\n\nfunction interface_method_static_method_bad(): string {\n  // Uncaught exception 'TypehintViolationException'\n  $c = MyInterface::class;\n  return $c::foo();\n}\n\nfunction abstract_class_static_method_bad(): string {\n  // Fatal error: Cannot call abstract method\n  $c = MyAbstractClass::class;\n  return $c::foo();\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Uninitialized Value" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"The code uses a variable that has not been initialized, leading to unpredictable or unintended results."}),"\n",(0,i.jsx)(n.p,{children:"Using uninitialized values can lead to undefined behaviors possibly resulting in crashes, security failures and invalid results."}),"\n",(0,i.jsx)(n.p,{children:"This can easily be fixed by assigning all variables to an initial value when declaring them."}),"\n",(0,i.jsx)(n.p,{children:"This, for example, in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct coordinates {\n  int x;\n  int y;\n};\n\nvoid foo() {\n  struct coordinates c;\n  c.x = 42;
1\n  c.y++; // uninitialized value c.y!\n\n  int z;\n  if (z == 0) { // uninitialized value z!\n    // something\n  }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy of an object via copy constructor where neither the source nor the copied variable are modified before the variable goes out of scope. Rather than the copy, a reference to the source object could be used to save memory."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n  int a;\n};\n\nint unnecessary_copy(A& x){\n  auto y = x; // calls copy constructor\n  return y.a; // y is not modified after copy, hence we could avoid the copy by adding & after auto as below\n}\n\nint use_reference_instead(A& x){\n  auto& y = x; // copy the ref only\n  return y.a;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary temporary copy of an intermediate object where copy is created to be passed down to a function unnecessarily. Instead, the intermediate object should either be moved into the callee or the type of the callee's parameter should be made ",(0,i.jsx)(n.code,{children:"const &"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A prime example of this occurs when we call a function with a call-by-value parameter as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(ExpensiveObject obj) {\n  // ....\n}\n\nvoid caller() {\n  callee(myExpensiveObj); // a copy of myExpensiveObj is created\n  // the copy is destroyed right after the call  \n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this case, when we call ",(0,i.jsx)(n.code,{children:"callee"}),", under the hood, a copy of the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is created to be passed to the function call. However, the copy might be unnecessary if"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"callee"})," doesn\u2019t modify its parameter \u2192 then we can change its type to ",(0,i.jsx)(n.code,{children:"const ExpensiveObject&"}),", getting rid of the copy at caller"]}),"\n",(0,i.jsxs)(n.li,{children:["even if ",(0,i.jsx)(n.code,{children:"callee"})," might modify the object, if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is never used later on, we can get rid of the copy by moving it instead: ",(0,i.jsx)(n.code,{children:"callee(std::move
1(myExpensiveObj))"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The analysis is careful about suggesting moves blindly though: if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is of type ",(0,i.jsx)(n.code,{children:"const & ExpensiveObject"})," then we also recommend that for move to work, const-reference needs to be removed."]}),"\n",(0,i.jsx)(n.p,{children:"PS: We check for other conditions on the argument here: e.g. it should be local to the procedure, as moving a non-local member might cause other memory correctness issues like use-after-move later on."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy into a field where"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the source is an rvalue-reference"}),"\n",(0,i.jsx)(n.li,{children:"the source is not modified before it goes out of scope or is destroyed."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that the copy can be modified since it has the ownership of the object."}),"\n",(0,i.jsx)(n.p,{children:"Fix: Rather than the copying into the field, the source should be moved into it."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n  std::vector<int> vec;\n};\n\nclass Test {\n  A mem_a;\n\n  void unnecessary_copy(A&& src) {\n   mem_a = src;\n   // fix is to move as follows\n   // mem_a = std::move(src);\n  }\n\n};\n\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary copy of an object via ",(0,i.jsx)(n.code,{children:"optional"})," value\nconstruction where the source is not modified before it goes out of scope.  To avoid the copy, we\ncan move the source object or change the callee's type."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void get_optional_value(std::optional<A> x) {}\n\nvoid pass_non_optional_value(A x) {\n  get_optional_value(x);\n  // fix is to move as follows\n  // get_optional_value(std::move(x));\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Return" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is similar to ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),", but reported when a callee returns a copied value and it is not modified in its caller.  We may be able to return const-ref typed value or try ",(0,i.jsx)(n.code,{children:"std::move"})," to avoid the copy."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"class MyClass {\n  T v;\n public:\n  T get() {\n    return v; // v is copied here, which is avoidable.\n  }\n};\n\nvoid caller(MyClass obj) {\n  T x = obj.get();\n  std::cout << x; // x is not modified.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment into Thrift" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This is similar to ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),", but is\nreported when copied into thrift fields."]}),"\n",(0,i.jsx)(n.h2,{id:"pure_function",children:"PURE_FUNCTION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Pure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-purity",children:"purity"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates pure functions. For instance, below functions would be marked as pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int local_write_pure(int x, int y) {\n  int k = x + y;\n  k++;\n  return k;\n}\n\n// no change to outside state, the local allocation is ok.\nint local_alloc_pure(ArrayList<Integer> list) {\n  ArrayList<Integer> list_new = new ArrayList<Integer>();\n  for (Integer el : list) {\n    list_new.add(el);\n  }\n  return list_new.size();\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"However, the following ones would not be pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void swap_impure(int[] array, int i, int j) {\n  int tmp = array[i];\n  array[i] = array[j]; // modifying the input array\n  array[j] = tmp;\n}\n\nint a = 0;\nvoid set_impure(int x, int y) {\n  a = x + y; //modifying a global variable\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Regex Op On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A potentially costly operation on a regular expression occurs on the UI thread."}),"\n",(0,i.jsx)(n.h2,{id:"retain_cycle",children:"RETAIN_CYCLE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A retain cycle is a situation when object A retains object B, and object B\nretains object A at the same time. Here is an example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n    Child *child; // Instance variables are implicitly __strong\n}\n@end\n@interface Child : NSObject {\n    Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.p,{children:'You can fix a retain cycle in ARC by using __weak variables or weak properties\nfor your "back links", i.e. links to direct or indirect parents in an object\nhierarchy:'}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n    Child *child;\n}\n@end\n@interface Child : NSObject {\n    __weak Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.h2,{id:"retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle No Weak Info" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A retain cycle is a situation when object A retains object B, and object B\nretains object A at the same time. Here is an example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n    Child *child; // Instance variables are implicitly __strong\n}\n@end\n@interface Child : NSObject {\n    Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.p,{children:'You can fix a retain cycle in ARC by using __weak variables or weak properties\nfor your "back links", i.e. links to direct or indirect parents in an object\nhierarchy:'}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n    Child *child;\n}\n@end\n@interface Child : NSObject {\n    __weak Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.h2,{id:"scope_leakage",children:"SCOPE_LEAKAGE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Scope Leakage" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-scope-leakage",children:"scope-leakage"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:'This issue type indicates that a class with scope annotation A stores a field\nwith whose (dynamic) type (or one of its super types) is annotated with scope\nB such that a scope nesting restriction is violated. By "stores", we mean\neither directly or transitively.'}),"\n",(0,i.jsx)(n.p,{children:"A configuration is used to list the set of scopes and the must-not-hold relation."}),"\n",(0,i.jsx)(n.p,{children:"In the following Java example, the set of scopes is Outer and Inner, and the must-not-hold\nrelation is simply {(Outer, Inner)}:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@ScopeType(value = Outer.class)\nclass ClassOfOuterScope {\n  final ClassOfInner c = new ClassOfInner(); // <-- warn here that ClassOfInner would leak.\n}\n\n@ScopeType(value = Inner.class)\nclass ClassOfInner {}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Here is a more detailed description of the analysis."}),"\n",(0,i.jsx)(n.p,{children:'This analysis operates over Java bytecode. It assumes that types (classes, interfaces, enums,\netc.) may be annotated with so-called scope annotations. The analysis is parameterized by a set\nof scopes and a "must-not-hold" relation over pairs of scopes, which it reads from a\nconfiguration file.'}),"\n",(0,i.jsx)(n.p,{children:'The analysis aims to detect violations of the following property: if there exist a path of\nfields from object OA to object OB and the type of OA (or one of its super-types) is annotated\nwith scope SA and the type of OB (or one of its super-types) is annotated with scope SB then\nmust-not-hold(SA, SB) must be false. Intuitively, the given objects have different scopes that\nshould not be nested, for example, different intended lifetimes, and a forbidden path from OA to\nOB results in OB "leaking" out of the scope SA.'}),"\n",(0,i.jsx)(n.p,{children:'The implementation reads a configuration to determine a list of (scope) "generators" for each\ntype of scope and a scope class for each type of scope. A generator for a scope type SA is given\nby the name of a class and a list of methods where it is understood that any of the methods\nlisted for the given class returns an object that is known to have scope SA. (This can be seen\nas a form of lightweight modeling.) A scope class is the name of the class that represents a\ngiven scope.'}),"\n",(0,i.jsx)(n.h2,{id:"self_in_block_passed_to_init",children:"SELF_IN_BLOCK_PASSED_TO_INIT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Self In Block Passed To Init" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check flags when ",(0,i.jsx)(n.code,{children:"self"})," is captured in a block that is passed to an initialiser method. That\ncould cause retain cycles if the initialiser code retains the block."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  [obj initWithHandler:^() {\n    [self foo];\n    ...\n  }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Instead it's better to use the ",(0,i.jsx)(n.code,{children:"weakSelf"}),"/",(0,i.jsx)(n.code,{children:"strongSelf"})," pattern."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  [obj initWithHandler:^() {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    if (strongSelf) {\n        [strongSelf foo];\n    }\n    ...\n  }];\n"})}),"\n",(0,i.jsx)(n.h2,{id:"sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Sensitive Data Flow" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A flow of sensitive data was detected from a source."}),"\n",(0,i.jsx)(n.h2,{id:"stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Stack Variable Address Escape" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Reported when an address pointing into the stack of the current\nfunction will escape to its calling context. Such addresses will\nbecome invalid by the time the function actually returns so are\npotentially dangerous."}),"\n",(0,i.jsx)(n.p,{children:"For example, directly returning a pointer to a local variable:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-C",children:'int* foo() {\n   int x = 42;\n   return &x; // <-- warn here that "&x" will escape\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"starvation",children:"STARVATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "UI Thread Starvation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported in Java, and specifically on Android. These reports are\ntriggered when a method that runs on the UI thread may block, thus potentially\nleading to an Application Not Responding error."}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.co
1de,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The issue is reported when a method deemed to run on the UI thread"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Makes a method call which may block."}),"\n",(0,i.jsx)(n.li,{children:"Takes a lock, and another thread takes the same lock, and before releasing it,\nmakes a call that may block."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Calls that may block are considered:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Certain I/O calls."}),"\n",(0,i.jsxs)(n.li,{children:["Two way ",(0,i.jsx)(n.code,{children:"Binder.transact"})," calls."]}),"\n",(0,i.jsx)(n.li,{children:"Certain OS calls."}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Future"})," or ",(0,i.jsx)(n.code,{children:"AsyncTask"})," calls to ",(0,i.jsx)(n.code,{children:"get"})," without timeouts, or with too large\ntimeouts."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress starvation reports in a method ",(0,i.jsx)(n.code,{children:"m()"})," use the\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STARVATION")'})," annotation, as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'  import android.annotation.SuppressLint;\n\n  @SuppressLint("STARVATION")\n  public void m() {\n  ...\n  }\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To signal to Infer that a method does not perform any blocking calls, despite\nappearences, you can use the ",(0,i.jsx)(n.code,{children:"@NonBlocking"})," annotation:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"  import com.facebook.infer.annotation.NonBlocking;\n\n  @NonBlocking\n  public void m() {\n  ...\n  }\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This instructs Infer to filter out any potentially blocking calls in ",(0,i.jsx)(n.code,{children:"m()"}),"\n(also, transitively), and thus any other method can expect no starvation reports\ndue to a call to ",(0,i.jsx)(n.code,{children:"m()"}),". You will need to set up your class path appropriately to\ninclude the JAR files in ",(0,i.jsx)(n.code,{children:"infer/annotations"})," for this annotation to work."]}),"\n",(0,i.jsx)(n.h2,{id:"static_constructor_stall",children:"STATIC_CONSTRUCTOR_STALL"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Static Constructor Stall" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-static-constructor-stall-checker",children:"static-constructor-stall-checker"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"Calling certain methods, for instance dispatch_once, during the static initialization of objects is risky. It could cause deadlocks, because other objects might not have been initialized yet."}),"\n",(0,i.jsx)(n.h2,{id:"static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Static Initialization Order Fiasco" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-siof",children:"siof"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This error is reported in C++. It fires when the initialization of a static\nvariable ",(0,i.jsx)(n.code,{children:"A"}),", accesses a static variable ",(0,i.jsx)(n.code,{children:"B"})," from another translation unit\n(usually another ",(0,i.jsx)(n.code,{children:".cpp"})," file). There are no guarantees whether ",(0,i.jsx)(n.code,{children:"B"})," has been\nalready initialized or not at that point."]}),"\n",(0,i.jsxs)(n.p,{children:["For more technical definition and techniques to avoid/remediate, see the\n",(0,i.jsx)(n.a,{href:"https://isocpp.org/wiki/faq/ctors#static-init-order",children:"FAQ"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strict_mode_violation",children:"STRICT_MODE_VIOLATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Strict Mode Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Android has a feature called\n",(0,i.jsx)(n.a,{href:"https://developer.android.com/reference/android/os/StrictMode",children:"strict mode"}),",\nwhich if enabled, will flag the occasions where the main thread makes a call\nthat results in disk I/O, waiting on a network socket, etc. The analysis\ncatching starvation errors and deadlocks (the ",(0,i.jsx)(n.code,{children:"--starvation"})," analysis) has the\nability to statically detect such violations."]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress this warning, it's enough to annotate the offending method with\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STRICT_MODE_VIOLATION")'}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "StrongSelf Not Checked" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports a potential issue when a block captures ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),"),\nthen one assigns this pointer to a local variable ",(0,i.jsx)(n.code,{children:"strongSelf"})," inside the block and uses this variable\nwithout checking first whether it is ",(0,i.jsx)(n.code,{children:"nil"}),". The problem here is that the weak pointer could be ",(0,i.jsx)(n.code,{children:"nil"})," at\nthe time when the block is executed. So, the correct usage is to first check whether ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a valid\npointer, and then use it."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    int y = strongSelf->x;\n    ...\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nAdd a check for ",(0,i.jsx)(n.code,{children:"nil"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n  int (^my_block)() = ^() {\n    __strong __typeof(weakSelf) strongSelf = weakSelf;\n    if (strongSelf) {\n      int y = strongSelf->x;\n      ...\n    }\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"}
1)," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"swift_npe",children:"SWIFT_NPE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Swift Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Pulse detected a Swift code path that reads from an Optional value known\nto be ",(0,i.jsx)(n.code,{children:"nil"}),". The dereference itself is unsafe -- not the surrounding\ntype annotation."]}),"\n",(0,i.jsxs)(n.p,{children:["The check is Swift-specific and considers an unwrap unsafe only when the\n",(0,i.jsx)(n.code,{children:".none"})," case is reachable along some path. Unwraps on values that are\nknown ",(0,i.jsx)(n.code,{children:".some"})," (literal payload, prior ",(0,i.jsx)(n.code,{children:"if let"})," / ",(0,i.jsx)(n.code,{children:"guard let"})," binding,\n",(0,i.jsx)(n.code,{children:"??"})," default) are silent. Unknown receivers (e.g. the result of an\nunmodelled extern call) are also silent."]}),"\n",(0,i.jsxs)(n.h2,{id:"force-unwrap-of-an-optional-whose-nil-case-is-reachable",children:["Force-unwrap of an Optional whose ",(0,i.jsx)(n.code,{children:"nil"})," case is reachable"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func unwrapsKnownNil_bad() {\n  let x: Int? = nil\n  _ = x!                 // SWIFT_NPE: x is known .none here\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Fix by binding the value before use:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func unwrapsKnownNil_good() {\n  let x: Int? = nil\n  if let v = x {\n    _ = v                 // OK: only reached on the .some branch\n  }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Or provide a default:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func defaultsToZero_good() {\n  let x: Int? = nil\n  let _ = x ?? 0          // OK: no force-unwrap\n}\n"})}),"\n",(0,i.jsxs)(n.h2,{id:"implicitly-unwrapped-optional-t-whose-underlying-value-is-nil",children:["Implicitly Unwrapped Optional (",(0,i.jsx)(n.code,{children:"T!"}),") whose underlying value is ",(0,i.jsx)(n.code,{children:"nil"})]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"T!"})," types are written as non-optional but compile to ",(0,i.jsx)(n.code,{children:"Optional<T>"})," and\ntrap on access if the value is ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func iuoFromBridge_bad(api: LegacyAPI) {\n  let s: String! = api.getUnannotatedString()   // ObjC returns nullable\n  _ = s.count                                   // SWIFT_NPE on .none\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Treat the value as a regular Optional and bind it explicitly:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func iuoBound_good(api: LegacyAPI) {\n  guard let s = api.getUnannotatedString() else { return }\n  _ = s.count                                   // OK\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["If the underlying source can be annotated, mark the ObjC return\n",(0,i.jsx)(n.code,{children:"_Nonnull"})," (or change the Swift type from ",(0,i.jsx)(n.code,{children:"T?"})," / ",(0,i.jsx)(n.code,{children:"T!"})," to ",(0,i.jsx)(n.code,{children:"T"}),") so the\nguarantee shows up in the signature."]}),"\n",(0,i.jsxs)(n.h2,{id:"optionalunsafelyunwrapped-on-a-known-nil-receiver",children:[(0,i.jsx)(n.code,{children:"Optional.unsafelyUnwrapped"})," on a known-",(0,i.jsx)(n.code,{children:"nil"})," receiver"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-swift",children:"func unsafelyUnwrappedNil_bad() {\n  let x: Int? = nil\n  _ = x.unsafelyUnwrapped       // SWIFT_NPE\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"unsafelyUnwrapped"})," has the same trap semantics as ",(0,i.jsx)(n.code,{children:"!"})," but skips the\nruntime check in optimised builds. Prefer the same fixes as above\n(",(0,i.jsx)(n.code,{children:"if let"}),", ",(0,i.jsx)(n.code,{children:"guard let"}),", ",(0,i.jsx)(n.code,{children:"??"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"swift_npe_latent",children:"SWIFT_NPE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Swift Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#swift_npe",children:"SWIFT_NPE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"taint_error",children:"TAINT_ERROR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Taint Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A taint flow was detected from a source to a sink"}),"\n",(0,i.jsx)(n.h2,{id:"thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Thread Safety Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This warning indicates a potential data race in Java. The analyser is called\nRacerD and this section gives brief but a mostly complete description of its\nfeatures. See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"RacerD page"})," for more in-depth information and\nexamples."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-what-is-a-data-race",children:"Thread-safety: What is a data race"}),"\n",(0,i.jsx)(n.p,{children:"Here a data race is a pair of accesses to the same member field such that:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"at least one is a write, and,"}),"\n",(0,i.jsx)(n.li,{children:"at least one occurs without any lock synchronization, and,"}),"\n",(0,i.jsx)(n.li,{children:"the two accesses occur on threads (if known) which can run in parallel."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-potential-fixes",children:"Thread-safety: Potential fixes"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Synchronizing the accesses (using the ",(0,i.jsx)(n.code,{children:"synchronized"})," keyword, thread-exclusion\nsuch as atomic objects, ",(0,i.jsx)(n.code,{children:"volatile"})," etc)."]}),"\n",(0,i.jsx)(n.li,{children:"Making an offending method private -- this will exclude it from being checked\nat the top level, though it will be checked if called by a public method which\nmay itself, e.g., hold a lock when calling it."}),"\n",(0,i.jsxs)(n.li,{children:["Putting the two accesses on the same thread, e.g., by using ",(0,i.jsx)(n.code,{children:"@MainThread"})," or\n",(0,i.jsx)(n.code,{children:"@ThreadConfined"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-conditions-checked-before-reporting",children:"Thread-safety: Conditions checked before reporting"}),"\n",(0,i.jsxs)(n.p,{children:["The class and method are not marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe(enableChecks = false)"}),", and,"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method is declared ",(0,i.jsx)(n.code,{children:"synchronized"}),", or employs (non-transitively) locking,\nor,"]}),"\n",(0,i.jsxs)(n.li,{children:["The class is not marked ",(0,i.jsx)(n.code,{children:"@NotThreadSafe"}),", and,","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The class/method is marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe,"})," or one of the configured synonyms\nin ",(0,i.jsx)(n.code,{children:".inferconfig"}),", or,"]}),"\n",(0,i.jsx)(n.li,{children:"A parent class, or an override method are marked with the above annotations."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["NB currently RacerD ",(0,i.jsxs)(n.strong,{children:["does not take into account ",(0,i.jsx)(n.code,{children:"@GuardedBy"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-thread-annotations-recognized-by-racerd",children:"Thread-safety: Thread annotations recognized by RacerD"}),"\n",(0,i.jsxs)(n.p,{children:["These class and method annotations imply the method is on the main thread:\n",(0,i.jsx)(n.code,{children:"@MainThread"}),", ",(0,i.jsx)(n.code,{children:"@UiThread"})]}),"\n",(0,i.jsxs)(n.p,{children:["These method annotations imply the method is on the main thread: ",(0,i.jsx)(n.code,{children:"@OnBind"}),",\n",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnMount"}),", ",(0,i.jsx)(n.code,{children:"@OnUnbind"}),", ",(0,i.jsx)(n.code,{children:"@OnUnmount"})]}),"\n",(0,i.jsx)(n.p,{children:"Both classes of annotations work through the inheritance tree (i.e. if a parent\nclass or method is marked with one of these annotations, so is the child class /\nmethod override)."}),"\n",(0,i.jsxs)(n.p,{children:["In addition to these, RacerD recognizes many lifecycle methods as necessarily\nrunning on the main thread, eg ",(0,i.jsx)(n.code,{children:"Fragment.onCreate"})," etc."]}),"\n",(0,i.jsxs)(n.p,{children:["Finally, the thread status of being on the main thread propagates backwards\nthrough the call graph (ie if ",(0,i.jsx)(n.code,{children:"foo"})," calls ",(0,i.jsx)(n.code,{children:"bar"})," and ",(0,i.jsx)(n.code,{children:"bar"})," is marked ",(0,i.jsx)(n.code,{children:"@UiThtread"}),"\nthen ",(0,i.jsx)(n.code,{children:"foo"})," is automatically considered on the main thread too). Calling\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),", ",(0,i.jsx)(n.code,{children:"assertOnUiThread"}),", ",(0,i.jsx)(n.code,{children:"checkOnMainThread"})," has the same effect."]}),"\n",(0,i.jsxs)(n.p,{children:["NB RacerD currently ",(0,i.jsxs)(n.strong,{children:["does not recognize ",(0,i.jsx)(n.code,{children:"@WorkerThread"}),", ",(0,i.jsx)(n.code,{children:"@BinderThread"})," or\n",(0,i.jsx)(n.code,{children:"@AnyThread"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-other-annotations-and-what-they-do",children:"Thread-safety: Other annotations and what they do"}),"\n",(0,i.jsxs)(n.p,{children:["These annotations can be found at ",(0,i.jsx)(n.code,{children:"com.facebook.infer.annotation.*"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@Functional"})," This is a method annotation indicating the method always returns\nthe same value. When a method ",(0,i.jsx)(n.code,{children:"foo"})," is annotated ",(0,i.jsx)(n.code,{children:"@Functional"}),", RacerD will\nignore any writes of the return value of ",(0,i.jsx)(n.code,{children:"foo"}),". For example, in\n",(0,i.jsx)(n.code,{children:"this.x = foo()"}),", the write to ",(0,i.jsx)(n.code,{children:"this.x"}
1)," is ignored. The reasoning is that if\nthe method returns the same value whenever it's called, any data race on\n",(0,i.jsx)(n.code,{children:"this.x"})," is benign, if that is the only write."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ThreadConfined"})," This is a class/method/field annotation which takes a single\nparameter which can be ",(0,i.jsx)(n.code,{children:"UI"}),", ",(0,i.jsx)(n.code,{children:"ANY"})," or a user chosen string. It indicates to\nRacerD a thread identifier for the class/method/field. Thus,\n",(0,i.jsx)(n.code,{children:"@ThreadConfined(UI)"})," is equivalent to ",(0,i.jsx)(n.code,{children:"@UiThread"}),", and ",(0,i.jsx)(n.code,{children:"@ThreadConfined(ANY)"}),"\nis equivalent to not having the annotation at all, for classes and methods.\nWhen this annotation is applied to a field it instructs Infer to assume\n(without checking) that all accesses to that field are made on the same thread\n(and can, therefore, not race by definition). The intention is that RacerD\nuses that to detect exclusion between accesses occurring on the same thread.\nHowever, only the UI thread is supported at this time, and any user provided\nvalue is considered equal to ",(0,i.jsx)(n.code,{children:"UI"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@VisibleForTesting"})," A method annotation making Infer consider the method as\neffectively ",(0,i.jsx)(n.code,{children:"private"}),". This means it will not be checked for races against\nother non-private methods of the class, but only if called by one."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ReturnsOwnership"})," A method annotation indicating that the method returns a\nfreshly owned object. Accesses to the returned value will not be considered\nfor data races, as the object is in-effect unique and not accessible yet from\nother threads. The main utility of this annotation is in interfaces, where\nInfer cannot look up the implementation and decide for itself."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error",children:"TOPL_ERROR"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"A violation of a Topl property (user-specified).\nThere is an execution path in the code that drives a Topl property from a start state to an error state."}),"\n",(0,i.jsx)(n.p,{children:"This indicates that the code has a user-defined undesired behavior."}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/docs/next/checker-topl#what-is-it",children:"Topl"})," for an example"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error_latent",children:"TOPL_ERROR_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#topl_error",children:"TOPL_ERROR"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete",children:"USE_AFTER_DELETE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}
1),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"delete"})," in C++ is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_delete",children:"USE_AFTER_DELETE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free",children:"USE_AFTER_FREE"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}
1),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"free"})," in C is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free_latent",children:"USE_AFTER_FREE_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_free",children:"USE_AFTER_FREE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime",children:"USE_AFTER_LIFETIME"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"The lifetime of an object has ended but that object is being\naccessed. For example, the address of a variable holding a C++ object\nis accessed after the variable has gone out of scope:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void foo() {\n     X* p;\n     { // new scope\n       X x = X();\n       p = &x;\n     } // x has gone out of scope\n     p->method(); // ERROR: you should not access *p after x has gone out of scope\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_lifetime",children:"USE_AFTER_LIFETIME"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation",children:"VECTOR_INVALIDATION"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["An address pointing into a C++ ",(0,i.jsx)(n.code,{children:"std::vector"})," might have become\ninvalid. This can happen when an address is taken into a vector, then\nthe vector is mutated in a way that might invalidate the address, for\nexample by adding elements to the vector, which might trigger a\nre-allocation of the entire vector contents (thereby invalidating the\npointers into the previous location of the contents)."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:'void deref_vector_element_after_push_back_bad(std::vector<int>& vec) {\n  int* elt = &vec[1];\n  int* y = elt;\n  vec.push_back(42); // if the array backing the vector was full already, this\n                     // will re-allocate it and copy the previous contents\n                     // into the new array, then delete the previous array\n  std::cout << *y << "\\n"; // bad: y might be invalid\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:["Category: ",(0,i.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#vector_invalidation",children:"VECTOR_INVALIDATION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"weak_self_in_no_escape_block",children:"WEAK_SELF_IN_NO_ESCAPE_BLOCK"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.em,{children:['Reported as "Weak Self In No Escape Block" b
1y ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),') is used in\na block, and this block is passed to a "no escaping" method. This means that\nthe block passed to that method won\'t be leaving the current scope, this is\nmarked with the annotation ',(0,i.jsx)(n.code,{children:"NS_NOESCAPE"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:['The issue here is that, because the block is "no escaping", there is no need to use\n',(0,i.jsx)(n.code,{children:"weakSelf"})," and ",(0,i.jsx)(n.code,{children:"strongSelf"})," but we can just use ",(0,i.jsx)(n.code,{children:"self"}),". This has the advantage of\nnot needing to deal with the added complexity of weak pointers, and it simplifies the\ncode."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  __weak __typeof(self) weakSelf = self;\n  [self foo:^() { //foo's first parameter is annotates with `NS_NOESCAPE`\n      [weakSelf bar];\n  }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Replace ",(0,i.jsx)(n.code,{children:"weakSelf"})," with ",(0,i.jsx)(n.code,{children:"self"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"  [self foo:^() {\n      [self bar];\n  }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453(e,n,s){s.d(n,{R:()=>l,x:()=>c});var r=s(6540);const i={},t=r.createContext(i);function l(e){const n=r.useContext(t);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.