diff --git a/404.html b/404.html index 1ad992e43da..d3459e7f29a 100644 --- a/404.html +++ b/404.html @@ -13,7 +13,7 @@ - +
diff --git a/assets/js/8fdeae25.4cf4e160.js b/assets/js/8fdeae25.4cf4e160.js new file mode 100644 index 00000000000..ff6e2997a71 --- /dev/null +++ b/assets/js/8fdeae25.4cf4e160.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6164],{7148:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>d});var l=s(7624),i=s(2172);const t={title:"Pulse",description:"General-purpose memory and value analysis engine."},r=void 0,a={id:"checker-pulse",title:"Pulse",description:"General-purpose memory and value analysis engine.",source:"@site/docs/checker-pulse.md",sourceDirName:".",slug:"/checker-pulse",permalink:"/docs/next/checker-pulse",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Pulse",description:"General-purpose memory and value analysis engine."},sidebar:"docs",previous:{title:"`printf()` Argument Types",permalink:"/docs/next/checker-printf-args"},next:{title:"Purity",permalink:"/docs/next/checker-purity"}},c={},d=[{value:"What is Infer?",id:"what-is-infer",level:2},{value:"Latent Issues",id:"latent-issues",level:2},{value:"Unknown Functions",id:"unknown-functions",level:2},{value:"Pulse x Nullsafe",id:"pulse-x-nullsafe",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function o(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.M)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,l.jsxs)(n.p,{children:["Activate with ",(0,l.jsx)(n.code,{children:"--pulse"}),"."]}),"\n",(0,l.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,l.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,l.jsx)(n.li,{children:"Erlang: Experimental"}),"\n",(0,l.jsx)(n.li,{children:"Hack: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,l.jsxs)(n.h2,{id:"what-is-infer",children:["What is Infer",":Pulse","?"]}),"\n",(0,l.jsxs)(n.p,{children:["Pulse is an interprocedural memory safety analysis. Pulse can detect, for instance, ",(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"Null dereferences"})," in Java. Errors are only reported when all conditions on the erroneous path are true regardless of input. Pulse should gradually replace the original ",(0,l.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"})," analysis of Infer. An example of a Null dereference found by Pulse is given below."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"class Person {\n Person emergencyContact;\n String address;\n\n Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n void create() {\n Person p = new Person();\n Person c = p.getEmergencyContact();\n // Null dereference here\n System.out.println(c.address);\n }\n\n void printContact(Person p) {\n // No null dereference, as we don't know anything about `p`\n System.out.println(p.getEmergencyContact().address);\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"How to run pulse for Java:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"infer run --pulse -- javac Test.java\n"})}),"\n",(0,l.jsxs)(n.p,{children:["Pulse reports a Null dereference on this file on ",(0,l.jsx)(n.code,{children:"create()"}),", as it tries to access the field ",(0,l.jsx)(n.code,{children:"address"})," of object ",(0,l.jsx)(n.code,{children:"c"}),", and ",(0,l.jsx)(n.code,{children:"c"})," has value ",(0,l.jsx)(n.code,{children:"null"}),". In contrast, Pulse gives no report for ",(0,l.jsx)(n.code,{children:"printContact(Person p)"}),", as we cannot be sure that ",(0,l.jsx)(n.code,{children:"p.getEmergencyContact()"})," will return ",(0,l.jsx)(n.code,{children:"null"}),". But, thanks to the fact that the analysis is ",(0,l.jsx)(n.em,{children:"inter-procedural"}),", Pulse will report a Null dereference on calls to ",(0,l.jsx)(n.code,{children:"printContact(p)"})," when it detects that ",(0,l.jsx)(n.code,{children:"p"})," is null."]}),"\n",(0,l.jsx)(n.h2,{id:"latent-issues",children:"Latent Issues"}),"\n",(0,l.jsxs)(n.p,{children:["When an error can occur only on some values of the parameters of the current function, Pulse does not report an issue. Such issues are called ",(0,l.jsx)(n.em,{children:"latent"}),". But, if Pulse then sees a call site at which all the conditions for the error are satisfied then the error becomes ",(0,l.jsx)(n.em,{children:"manifest"})," and is reported. This example (in C) illustrates how latent issues are created and then reported when they become manifest:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"// for more realism, imagine that this function does other things as well\nvoid set_to_null_if_positive(int n, int* p) {\n if (n > 0) {\n p = NULL;\n }\n}\n\nvoid latent_null_dereference(int n, int* p) {\n set_to_null_if_positive(n, p);\n *p = 42; // NULL dereference! but only if n > 0 so no report yet\n}\n\nvoid manifest_error(int *p) {\n // no way to avoid the bug here => Pulse reports an error\n latent_null_dereference(1, p);\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"unknown-functions",children:"Unknown Functions"}),"\n",(0,l.jsx)(n.p,{children:"In order to avoid false positives, Pulse makes optimistic assumptions about calls to unknown functions. Unknown functions (or unknown methods) are functions for which Infer didn't find any code. For example, it could be because the function belongs to a third-party library and we know only its signature, or because a function is made through a function pointer that Pulse wasn't able to resolve to a concrete function. In either case, Pulse will scramble the parts of the state reachable from the parameters of the call. In general, this helps avoid false positives but note that this may cause false negatives as well as false positives:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"void unknown(int* p); // third-party code that does [*p = 5]\n // Infer doesn't have access to that code\n\nvoid false_negative() {\n int* x = (int*) malloc(sizeof(int));\n if (x) {\n // unknown call to x makes Pulse forget that x was allocated, in case it frees x\n unknown(x);\n }\n} // no memory leak reported: false negative!\n\nvoid false_positive(int *x) {\n unknown(x); // this sets *x to 5\n if (x != 5) {\n // unreachable\n int* p = NULL;\n *p = 42; // false positive reported here\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"You can check if a given function called any unknown functions by inspecting its Pulse summary. For example, for the code above:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-console",children:"$ infer --pulse-only -- clang -c unknown_code.c\n No issues found\n$ infer debug --procedures --procedures-filter 'false_negative' --procedures-summary\n...\n skipped_calls={ unknown -> call to skipped function occurs here }\n"})}),"\n",(0,l.jsx)(n.h2,{id:"pulse-x-nullsafe",children:"Pulse x Nullsafe"}),"\n",(0,l.jsxs)(n.p,{children:["Nullsafe is a type checker for ",(0,l.jsx)(n.code,{children:"@Nullable"})," annotations for Java. Classes following the Nullsafe discipline are annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["Consider the classes ",(0,l.jsx)(n.code,{children:"Person"})," and ",(0,l.jsx)(n.code,{children:"Registry"})," from the previous example. Assuming that class ",(0,l.jsx)(n.code,{children:"Person"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". In this case, we also annotate ",(0,l.jsx)(n.code,{children:"getEmergencyContact()"})," with ",(0,l.jsx)(n.code,{children:"@Nullable"}),", to make explicit that this method can return the ",(0,l.jsx)(n.code,{children:"null"})," value. There is still the risk that classes depending on ",(0,l.jsx)(n.code,{children:"Person"})," have Null dereferences. In this case, Pulse would report a Null dereference on ",(0,l.jsx)(n.code,{children:"Registry"}),". It could also be the case that class ",(0,l.jsx)(n.code,{children:"Registry"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". By default Pulse reports on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files too, see the ",(0,l.jsx)(n.code,{children:"--pulse-nullsafe-report-npe"})," option (Facebook-specific: Pulse does not report on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files)."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"@Nullsafe(Nullsafe.Mode.LOCAL)\nclass Person {\n Person emergencyContact;\n String address;\n\n @Nullable Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n ... // Pulse reports here\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,l.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return",children:"BAD_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return_latent",children:"BAD_RETURN_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#config_usage",children:"CONFIG_USAGE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value_latent",children:"PULSE_UNINITIALIZED_VALUE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(o,{...e})}):o(e)}},2172:(e,n,s)=>{s.d(n,{I:()=>a,M:()=>r});var l=s(1504);const i={},t=l.createContext(i);function r(e){const n=l.useContext(t);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),l.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8fdeae25.bf070cb1.js b/assets/js/8fdeae25.bf070cb1.js deleted file mode 100644 index 67ae98aa6b2..00000000000 --- a/assets/js/8fdeae25.bf070cb1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6164],{7148:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>d});var l=s(7624),i=s(2172);const t={title:"Pulse",description:"General-purpose memory and value analysis engine."},r=void 0,a={id:"checker-pulse",title:"Pulse",description:"General-purpose memory and value analysis engine.",source:"@site/docs/checker-pulse.md",sourceDirName:".",slug:"/checker-pulse",permalink:"/docs/next/checker-pulse",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Pulse",description:"General-purpose memory and value analysis engine."},sidebar:"docs",previous:{title:"`printf()` Argument Types",permalink:"/docs/next/checker-printf-args"},next:{title:"Purity",permalink:"/docs/next/checker-purity"}},c={},d=[{value:"What is Infer?",id:"what-is-infer",level:2},{value:"Latent Issues",id:"latent-issues",level:2},{value:"Unknown Functions",id:"unknown-functions",level:2},{value:"Pulse x Nullsafe",id:"pulse-x-nullsafe",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function o(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.M)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,l.jsxs)(n.p,{children:["Activate with ",(0,l.jsx)(n.code,{children:"--pulse"}),"."]}),"\n",(0,l.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,l.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,l.jsx)(n.li,{children:"Erlang: Experimental"}),"\n",(0,l.jsx)(n.li,{children:"Hack: No"}),"\n",(0,l.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,l.jsxs)(n.h2,{id:"what-is-infer",children:["What is Infer",":Pulse","?"]}),"\n",(0,l.jsxs)(n.p,{children:["Pulse is an interprocedural memory safety analysis. Pulse can detect, for instance, ",(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"Null dereferences"})," in Java. Errors are only reported when all conditions on the erroneous path are true regardless of input. Pulse should gradually replace the original ",(0,l.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"})," analysis of Infer. An example of a Null dereference found by Pulse is given below."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"class Person {\n Person emergencyContact;\n String address;\n\n Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n void create() {\n Person p = new Person();\n Person c = p.getEmergencyContact();\n // Null dereference here\n System.out.println(c.address);\n }\n\n void printContact(Person p) {\n // No null dereference, as we don't know anything about `p`\n System.out.println(p.getEmergencyContact().address);\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"How to run pulse for Java:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"infer run --pulse -- javac Test.java\n"})}),"\n",(0,l.jsxs)(n.p,{children:["Pulse reports a Null dereference on this file on ",(0,l.jsx)(n.code,{children:"create()"}),", as it tries to access the field ",(0,l.jsx)(n.code,{children:"address"})," of object ",(0,l.jsx)(n.code,{children:"c"}),", and ",(0,l.jsx)(n.code,{children:"c"})," has value ",(0,l.jsx)(n.code,{children:"null"}),". In contrast, Pulse gives no report for ",(0,l.jsx)(n.code,{children:"printContact(Person p)"}),", as we cannot be sure that ",(0,l.jsx)(n.code,{children:"p.getEmergencyContact()"})," will return ",(0,l.jsx)(n.code,{children:"null"}),". But, thanks to the fact that the analysis is ",(0,l.jsx)(n.em,{children:"inter-procedural"}),", Pulse will report a Null dereference on calls to ",(0,l.jsx)(n.code,{children:"printContact(p)"})," when it detects that ",(0,l.jsx)(n.code,{children:"p"})," is null."]}),"\n",(0,l.jsx)(n.h2,{id:"latent-issues",children:"Latent Issues"}),"\n",(0,l.jsxs)(n.p,{children:["When an error can occur only on some values of the parameters of the current function, Pulse does not report an issue. Such issues are called ",(0,l.jsx)(n.em,{children:"latent"}),". But, if Pulse then sees a call site at which all the conditions for the error are satisfied then the error becomes ",(0,l.jsx)(n.em,{children:"manifest"})," and is reported. This example (in C) illustrates how latent issues are created and then reported when they become manifest:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"// for more realism, imagine that this function does other things as well\nvoid set_to_null_if_positive(int n, int* p) {\n if (n > 0) {\n p = NULL;\n }\n}\n\nvoid latent_null_dereference(int n, int* p) {\n set_to_null_if_positive(n, p);\n *p = 42; // NULL dereference! but only if n > 0 so no report yet\n}\n\nvoid manifest_error(int *p) {\n // no way to avoid the bug here => Pulse reports an error\n latent_null_dereference(1, p);\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"unknown-functions",children:"Unknown Functions"}),"\n",(0,l.jsx)(n.p,{children:"In order to avoid false positives, Pulse makes optimistic assumptions about calls to unknown functions. Unknown functions (or unknown methods) are functions for which Infer didn't find any code. For example, it could be because the function belongs to a third-party library and we know only its signature, or because a function is made through a function pointer that Pulse wasn't able to resolve to a concrete function. In either case, Pulse will scramble the parts of the state reachable from the parameters of the call. In general, this helps avoid false positives but note that this may cause false negatives as well as false positives:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"void unknown(int* p); // third-party code that does [*p = 5]\n // Infer doesn't have access to that code\n\nvoid false_negative() {\n int* x = (int*) malloc(sizeof(int));\n if (x) {\n // unknown call to x makes Pulse forget that x was allocated, in case it frees x\n unknown(x);\n }\n} // no memory leak reported: false negative!\n\nvoid false_positive(int *x) {\n unknown(x); // this sets *x to 5\n if (x != 5) {\n // unreachable\n int* p = NULL;\n *p = 42; // false positive reported here\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"You can check if a given function called any unknown functions by inspecting its Pulse summary. For example, for the code above:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-console",children:"$ infer --pulse-only -- clang -c unknown_code.c\n No issues found\n$ infer debug --procedures --procedures-filter 'false_negative' --procedures-summary\n...\n skipped_calls={ unknown -> call to skipped function occurs here }\n"})}),"\n",(0,l.jsx)(n.h2,{id:"pulse-x-nullsafe",children:"Pulse x Nullsafe"}),"\n",(0,l.jsxs)(n.p,{children:["Nullsafe is a type checker for ",(0,l.jsx)(n.code,{children:"@Nullable"})," annotations for Java. Classes following the Nullsafe discipline are annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["Consider the classes ",(0,l.jsx)(n.code,{children:"Person"})," and ",(0,l.jsx)(n.code,{children:"Registry"})," from the previous example. Assuming that class ",(0,l.jsx)(n.code,{children:"Person"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". In this case, we also annotate ",(0,l.jsx)(n.code,{children:"getEmergencyContact()"})," with ",(0,l.jsx)(n.code,{children:"@Nullable"}),", to make explicit that this method can return the ",(0,l.jsx)(n.code,{children:"null"})," value. There is still the risk that classes depending on ",(0,l.jsx)(n.code,{children:"Person"})," have Null dereferences. In this case, Pulse would report a Null dereference on ",(0,l.jsx)(n.code,{children:"Registry"}),". It could also be the case that class ",(0,l.jsx)(n.code,{children:"Registry"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". By default Pulse reports on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files too, see the ",(0,l.jsx)(n.code,{children:"--pulse-nullsafe-report-npe"})," option (Facebook-specific: Pulse does not report on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files)."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"@Nullsafe(Nullsafe.Mode.LOCAL)\nclass Person {\n Person emergencyContact;\n String address;\n\n @Nullable Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n ... // Pulse reports here\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,l.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return",children:"BAD_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return_latent",children:"BAD_RETURN_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#config_usage",children:"CONFIG_USAGE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value_latent",children:"PULSE_UNINITIALIZED_VALUE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(o,{...e})}):o(e)}},2172:(e,n,s)=>{s.d(n,{I:()=>a,M:()=>r});var l=s(1504);const i={},t=l.createContext(i);function r(e){const n=l.useContext(t);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),l.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c359af60.5a432b21.js b/assets/js/c359af60.5a432b21.js deleted file mode 100644 index 326b6e7a504..00000000000 --- a/assets/js/c359af60.5a432b21.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8544],{7872:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>o});var i=s(7624),r=s(2172);const t={title:"List of all issue types"},a=void 0,l={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:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"List of all issue types"},sidebar:"docs",previous:{title:"List of all checkers",permalink:"/docs/next/all-checkers"},next:{title:"Annotation Reachability",permalink:"/docs/next/checker-annotation-reachability"}},c={},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_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:"BIABDUCTION_MEMORY_LEAK",id:"biabduction_memory_leak",level:2},{value:"BIABDUCTION_RETAIN_CYCLE",id:"biabduction_retain_cycle",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:"CHECKERS_PRINTF_ARGS",id:"checkers_printf_args",level:2},{value:"CONFIG_IMPACT",id:"config_impact",level:2},{value:"CONFIG_IMPACT_STRICT",id:"config_impact_strict",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:"CREATE_INTENT_FROM_URI",id:"create_intent_from_uri",level:2},{value:"CROSS_SITE_SCRIPTING",id:"cross_site_scripting",level:2},{value:"CXX_REF_CAPTURED_IN_BLOCK",id:"cxx_ref_captured_in_block",level:2},{value:"DANGLING_POINTER_DEREFERENCE",id:"dangling_pointer_dereference",level:2},{value:"DATALOG_FACT",id:"datalog_fact",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:"DIVIDE_BY_ZERO",id:"divide_by_zero",level:2},{value:"EMPTY_VECTOR_ACCESS",id:"empty_vector_access",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:"EXPOSED_INSECURE_INTENT_HANDLING",id:"exposed_insecure_intent_handling",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},{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:"INSECURE_INTENT_HANDLING",id:"insecure_intent_handling",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:"JAVASCRIPT_INJECTION",id:"javascript_injection",level:2},{value:"LAB_RESOURCE_LEAK",id:"lab_resource_leak",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:"LOGGING_PRIVATE_DATA",id:"logging_private_data",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_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:"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_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:"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:"NULL_DEREFERENCE",id:"null_dereference",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:"PREMATURE_NIL_TERMINATION_ARGUMENT",id:"premature_nil_termination_argument",level:2},{value:"PULSE_CONST_REFABLE",id:"pulse_const_refable",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_UNINITIALIZED_CONST",id:"pulse_uninitialized_const",level:2},{value:"PULSE_UNINITIALIZED_VALUE",id:"pulse_uninitialized_value",level:2},{value:"PULSE_UNINITIALIZED_VALUE_LATENT",id:"pulse_uninitialized_value_latent",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:"PURE_FUNCTION",id:"pure_function",level:2},{value:"QUANDARY_TAINT_ERROR",id:"quandary_taint_error",level:2},{value:"REGEX_OP_ON_UI_THREAD",id:"regex_op_on_ui_thread",level:2},{value:"RESOURCE_LEAK",id:"resource_leak",level:2},{value:"Resource leak in C",id:"resource-leak-in-c",level:3},{value:"Resource leak in Java",id:"resource-leak-in-java",level:3},{value:"Basics and Standard Idiom",id:"basics-and-standard-idiom",level:3},{value:"Multiple Resources Bugs",id:"multiple-resources-bugs",level:4},{value:"Nested_Allocations",id:"nested_allocations",level:3},{value:"Allocation of JSonParser and Cursor resources",id:"allocation-of-jsonparser-and-cursor-resources",level:3},{value:"Escaping resources and exceptions",id:"escaping-resources-and-exceptions",level:3},{value:"Java 7's try-with-resources",id:"java-7s-try-with-resources",level:3},{value:"RETAIN_CYCLE",id:"retain_cycle",level:2},{value:"SCOPE_LEAKAGE",id:"scope_leakage",level:2},{value:"SENSITIVE_DATA_FLOW",id:"sensitive_data_flow",level:2},{value:"SHELL_INJECTION",id:"shell_injection",level:2},{value:"SHELL_INJECTION_RISK",id:"shell_injection_risk",level:2},{value:"SQL_INJECTION",id:"sql_injection",level:2},{value:"SQL_INJECTION_RISK",id:"sql_injection_risk",level:2},{value:"STACK_VARIABLE_ADDRESS_ESCAPE",id:"stack_variable_address_escape",level:2},{value:"STARVATION",id:"starvation",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:"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:"UNINITIALIZED_VALUE",id:"uninitialized_value",level:2},{value:"UNTRUSTED_BUFFER_ACCESS",id:"untrusted_buffer_access",level:2},{value:"UNTRUSTED_DESERIALIZATION",id:"untrusted_deserialization",level:2},{value:"UNTRUSTED_DESERIALIZATION_RISK",id:"untrusted_deserialization_risk",level:2},{value:"UNTRUSTED_ENVIRONMENT_CHANGE_RISK",id:"untrusted_environment_change_risk",level:2},{value:"UNTRUSTED_FILE",id:"untrusted_file",level:2},{value:"UNTRUSTED_FILE_RISK",id:"untrusted_file_risk",level:2},{value:"UNTRUSTED_HEAP_ALLOCATION",id:"untrusted_heap_allocation",level:2},{value:"UNTRUSTED_INTENT_CREATION",id:"untrusted_intent_creation",level:2},{value:"UNTRUSTED_URL_RISK",id:"untrusted_url_risk",level:2},{value:"UNTRUSTED_VARIABLE_LENGTH_ARRAY",id:"untrusted_variable_length_array",level:2},{value:"USER_CONTROLLED_SQL_RISK",id:"user_controlled_sql_risk",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",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.M)(),...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.jsxs)(n.p,{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.jsxs)(n.p,{children:['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] with 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.jsxs)(n.p,{children:['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_key",children:"BAD_KEY"}),"\n",(0,i.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{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.jsxs)(n.p,{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:"biabduction_memory_leak",children:"BIABDUCTION_MEMORY_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#memory_leak",children:"MEMORY_LEAK"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"biabduction_retain_cycle",children:"BIABDUCTION_RETAIN_CYCLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Retain Cycle" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#retain_cycle",children:"RETAIN_CYCLE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"}),"\n",(0,i.jsxs)(n.p,{children:['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:(NSOperationQueue*)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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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.jsxs)(n.p,{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.jsxs)(n.p,{children:['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:"checkers_printf_args",children:"CHECKERS_PRINTF_ARGS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Printf Args" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-printf-args",children:"printf-args"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error is reported when the argument types to a ",(0,i.jsx)(n.code,{children:"printf"})," method do not match the format string."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' void stringInsteadOfInteger(PrintStream out) {\n out.printf("Hello %d", "world");\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"Action: fix the mismatch between format string and argument types."}),"\n",(0,i.jsx)(n.h2,{id:"config_impact",children:"CONFIG_IMPACT"}),"\n",(0,i.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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_usage",children:"CONFIG_USAGE"}),"\n",(0,i.jsxs)(n.p,{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.jsxs)(n.p,{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.jsxs)(n.p,{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:"create_intent_from_uri",children:"CREATE_INTENT_FROM_URI"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Create Intent From Uri" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Create an intent/start a component using a (possibly user-controlled) URI. may or may not be an issue depending on where the URI comes from."}),"\n",(0,i.jsx)(n.h2,{id:"cross_site_scripting",children:"CROSS_SITE_SCRIPTING"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Cross Site Scripting" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data flows into HTML; XSS risk."}),"\n",(0,i.jsx)(n.h2,{id:"cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"}),"\n",(0,i.jsxs)(n.p,{children:['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:"dangling_pointer_dereference",children:"DANGLING_POINTER_DEREFERENCE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Dangling Pointer Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"datalog_fact",children:"DATALOG_FACT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Datalog Fact" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-datalog",children:"datalog"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Datalog fact used as input for a datalog solver."}),"\n",(0,i.jsx)(n.h2,{id:"data_flow_to_sink",children:"DATA_FLOW_TO_SINK"}),"\n",(0,i.jsxs)(n.p,{children:['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.jsxs)(n.p,{children:['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 something 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.jsxs)(n.p,{children:['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:"divide_by_zero",children:"DIVIDE_BY_ZERO"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Divide By Zero" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"empty_vector_access",children:"EMPTY_VECTOR_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Empty Vector Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This error type is reported only in C++, in versions >= C++11."}),"\n",(0,i.jsx)(n.p,{children:"The code is trying to access an element of a vector that Infer believes to be\nempty. Such an access will cause undefined behavior at runtime."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#includeThis 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 const&
so that no unnecessary copy is created at the callsite of the function.
For example,
#include <vector>
int read_first(const std::vector<int>& vec) { return vec[0]; }
void const_refable(std::vector<int> vec) {
int first = read_first(vec); // vec is never modified, so the parameter should have type const&
}
Reported as "Dict Missing Key" by pulse.
+This issue is similar to UNINITIALIZED_VALUE
issue, but it is to warn
+reading a missing key of dictionary in Hack.
For example, in the following code, the dictionary $d
has no entry for bye
, so reading
+$d['bye']
will throw the OutOfBoundsException
exception, which is usually unexpected from
+developers. We can use a safer function idx
instead when keys of a dictionary is unclear.
function simple_bad() : int {
$d = dict['hi' => 42, 'hello' => 52];
return $d['bye'];
}
Reported as "Read-only Shared Parameter" by pulse.
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, consider 1) passing the raw pointer instead and 2) use std::shared_ptr::get
at callsites.
weakSelf
with self
:
[self foo:^() {
[self bar];
}];
Limitations: To keep this check simple and intra-procedural, we rely on names to find weakSelf
:
-we assume that any captured weak pointer whose name contains "self" is a weak reference to self
.
self
.