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:"#include \nint foo(){\n const std::vector vec;\n return vec[0]; // Empty vector access reported here\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase",children:"EXECUTION_TIME_COMPLEXITY_INCREASE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Complexity Increase" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of a\nprogram increases in degree: e.g. from constant to linear or from\nlogarithmic to quadratic. This issue type is only reported in\ndifferential mode: i.e when we are comparing the cost analysis results of\ntwo runs of infer on a file. Check out examples in ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost#examples",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase_ui_thread",children:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Complexity Increase Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of the procedure increases in degree ",(0,i.jsx)(n.strong,{children:"and"})," the procedure runs on the UI (main) thread."]}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_unreachable_at_exit",children:"EXECUTION_TIME_UNREACHABLE_AT_EXIT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Unreachable At Exit" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates that the program's execution doesn't reach\nthe exit node (where our analysis computes the final cost of the\nprocedure). Hence, we cannot compute a static bound for the procedure."}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void exit_unreachable() {\n exit(0); // modeled as unreachable\n}\n\nvoid infeasible_path_unreachable() {\n Preconditions.checkState(false); // like assert false, state pruned to bottom\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_execution_time",children:"EXPENSIVE_EXECUTION_TIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Expensive Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["[EXPERIMENTAL] This warning indicates that the procedure has non-constant and non-top execution cost. By default, this issue type is disabled. To enable it, set ",(0,i.jsx)(n.code,{children:"enabled=true"})," in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/base/costKind.ml#L55",children:"costKind.ml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For instance, a simple example where we report this issue is a function with linear cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int sum_linear(ArrayList list){\n int sum = 0;\n for (Integer el: list){\n sum += el;\n }\n return sum;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_loop_invariant_call",children:"EXPENSIVE_LOOP_INVARIANT_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Expensive Loop Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["We report this issue type when a function is ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#invariant_call",children:"loop-invariant"})," and also expensive (i.e. at least has linear complexity as determined by the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"})," analysis)."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int incr(int x) {\n return x + 1;\n}\n\n// incr will not be hoisted since it is cheap(constant time)\nvoid foo_linear(int size) {\n int x = 10;\n for (int i = 0; i < size; i++) {\n incr(x); // constant call, don't hoist\n }\n}\n\n// call to foo_linear will be hoisted since it is expensive(linear in size).\nvoid symbolic_expensive_hoist(int size) {\n for (int i = 0; i < size; i++) {\n foo_linear(size); // hoist\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"exposed_insecure_intent_handling",children:"EXPOSED_INSECURE_INTENT_HANDLING"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Exposed Insecure Intent Handling" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"guardedby_violation",children:"GUARDEDBY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "GuardedBy Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A field annotated with ",(0,i.jsx)(n.code,{children:"@GuardedBy"})," is being accessed by a call-chain that starts at a non-private method without synchronization."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'class C {\n @GuardedBy("this")\n String f;\n\n void foo(String s) {\n f = s; // unprotected access here\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Action: Protect the offending access by acquiring the lock indicated by the ",(0,i.jsx)(n.code,{children:"@GuardedBy(...)"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"impure_function",children:"IMPURE_FUNCTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Impure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates impure functions. For instance, below functions would be marked as impure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void makeAllZero_impure(ArrayList list) {\n Iterator listIterator = list.iterator();\n while (listIterator.hasNext()) {\n Foo foo = listIterator.next();\n foo.x = 0;\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Inefficient Keyset Iterator" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"inefficient-keyset-iterator"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue is raised when"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["iterating over a HashMap with ",(0,i.jsx)(n.code,{children:"ketSet()"})," iterator"]}),"\n",(0,i.jsx)(n.li,{children:"looking up the key each time"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void inefficient_loop_bad(HashMap testMap) {\n for (String key : testMap.keySet()) {\n Integer value = testMap.get(key); // extra look-up cost\n foo(key, value);\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Instead, it is more efficient to iterate over the loop with ",(0,i.jsx)(n.code,{children:"entrySet"})," which returns key-vaue pairs and gets rid of the hashMap lookup."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void efficient_loop_ok(HashMap testMap) {\n for (Map.Entry entry : testMap.entrySet()) {\n String key = entry.getKey();\n Integer value = entry.getValue();\n foo(key, value);\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_big",children:"INFERBO_ALLOC_IS_BIG"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is passed a large constant value (>=10^6). For example, ",(0,i.jsx)(n.code,{children:"int n = 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument or make sure it is really needed."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_negative",children:"INFERBO_ALLOC_IS_NEGATIVE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a negative size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_zero",children:"INFERBO_ALLOC_IS_ZERO"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Zero" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a zero size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 3; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_ZERO"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_big",children:"INFERBO_ALLOC_MAY_BE_BIG"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc May Be Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a large value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n < A_SMALL_NUMBER) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_negative",children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc May Be Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a negative value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : -5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n > 0) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"infinite_execution_time",children:"INFINITE_EXECUTION_TIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Infinite Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This warning indicates that Infer was not able to determine a static\nupper bound on the execution cost of the procedure. By default, this\nissue type is disabled."}),"\n",(0,i.jsx)(n.h3,{id:"example-1-t-due-to-expressivity",children:"Example 1: T due to expressivity"}),"\n",(0,i.jsx)(n.p,{children:"For instance, Inferbo's interval analysis is limited to affine\nexpressions. Hence, we can't statically estimate an upper bound on the\nbelow example and obtain T(unknown) cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: square root(x), got T\nvoid square_root_FP(int x) {\n int i = 0;\n while (i * i < x) {\n i++;\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"example-2-t-due-to-unmodeled-calls",children:"Example 2: T due to unmodeled calls"}),"\n",(0,i.jsx)(n.p,{children:"Another common case where we get T cost is when Infer cannot statically determine the range of values for loop bounds. For instance,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void loop_over_charArray_FP(StringBuilder builder, String input) {\n for (Character c : input.toCharArray()) {}\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Here, Infer does not have any InferBo models for the range of values returned by ",(0,i.jsx)(n.code,{children:"String.toCharArray"}),", hence it cannot determine that we will be iterating over a char array in the size of ",(0,i.jsx)(n.code,{children:"input"})," string."]}),"\n",(0,i.jsxs)(n.p,{children:["To teach InferBo about such library calls, they should be semantically modeled in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/bufferoverrun/bufferOverrunModels.ml",children:"InferBo"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"example-3-t-due-to-calling-another-t-costed-function",children:"Example 3: T due to calling another T-costed function"}),"\n",(0,i.jsx)(n.p,{children:"Since the analysis is inter-procedural, another example we can have T cost is if at least one of the callees has T cost."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: constant, got T\nvoid call_top_cost_FP() {\n square_root_FP(1); // square_root_FP has Top cost\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"insecure_intent_handling",children:"INSECURE_INTENT_HANDLING"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Insecure Intent Handling" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L1" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when integer overflow occurred by integer operations such as addition, subtraction,\nand multiplication. For example, ",(0,i.jsx)(n.code,{children:"int n = INT_MAX; int m = n + 3;"})," generates a INTEGER_OVERFLOW_L1\non ",(0,i.jsx)(n.code,{children:"n + 3"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Integer overflows reports fall into several "buckets" corresponding to the expected precision of the\nreport. The higher the number, the more likely it is to be a false positive.'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,i.jsx)(n.em,{children:"must"})," be unsafe. For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [1,1]"})," in 32-bit signed integer type."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,i.jsx)(n.code,{children:"L1"}),", when it ",(0,i.jsx)(n.em,{children:"may"})," be unsafe. For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [0,1]"})," in 32-bit signed integer type. Note that the integer of RHS\ncan be 0, which is safe."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L5"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"U5"}),": A binary integer operation is unsafe by unknown values, which are usually from unknown\nfunction calls."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l2",children:"INTEGER_OVERFLOW_L2"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L2" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l5",children:"INTEGER_OVERFLOW_L5"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_u5",children:"INTEGER_OVERFLOW_U5"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow U5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Interface Not Thread Safe" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error indicates that you have invoked an interface method not annotated\nwith ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," from a thread-safe context (e.g., code that uses locks or is\nmarked ",(0,i.jsx)(n.code,{children:"@ThreadSafe"}),"). The fix is to add the ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," annotation to the\ninterface or to the interface method. For background on why these annotations\nare needed, see the detailed explanation\n",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd#interface-not-thread-safe",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"invalid_sil",children:"INVALID_SIL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Invalid Sil" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-sil-validation",children:"sil-validation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The SIL instruction does not conform to the expected subset of instructions\nexpected for the front-end of the language for the analyzed code."}),"\n",(0,i.jsx)(n.h2,{id:"invariant_call",children:"INVARIANT_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"We report this issue type when a function call is loop-invariant and hoistable, i.e."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the function has no side side effects (pure)"}),"\n",(0,i.jsx)(n.li,{children:"has invariant arguments and result (i.e. have the same value in all loop iterations)"}),"\n",(0,i.jsx)(n.li,{children:"it is guaranteed to execute, i.e. it dominates all loop sources"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int foo(int x, int y) {\n return x + y;\n}\n\n\nvoid invariant_hoist(int size) {\n int x = 10;\n int y = 5;\n for (int i = 0; i < size; i++) {\n foo(x, y); // hoistable\n }\n }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Ipc On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A blocking ",(0,i.jsx)(n.code,{children:"Binder"})," IPC call occurs on the UI thread."]}),"\n",(0,i.jsx)(n.h2,{id:"javascript_injection",children:"JAVASCRIPT_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Javascript Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data flows into JavaScript."}),"\n",(0,i.jsx)(n.h2,{id:"lab_resource_leak",children:"LAB_RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lab Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-resource-leak-lab",children:"resource-leak-lab"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Toy issue."}),"\n",(0,i.jsx)(n.h2,{id:"lockless_violation",children:"LOCKLESS_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lockless Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A method implements an interface signature annotated with ",(0,i.jsx)(n.code,{children:"@Lockless"})," but which transitively acquires a lock."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"Interface I {\n @Lockless\n public void no_lock();\n}\n\nclass C implements I {\n private synchronized do_lock() {}\n\n public void no_lock() { // this method should not acquire any locks\n do_lock();\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lock Consistency Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is an error reported on C++ and Objective C classes whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Some class method directly uses locking primitives (not transitively)."}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which writes to some member ",(0,i.jsx)(n.code,{children:"x"})," while holding a lock."]}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which reads ",(0,i.jsx)(n.code,{children:"x"})," without holding a lock."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The above may happen through a chain of calls. Above, ",(0,i.jsx)(n.code,{children:"x"})," may also be a\ncontainer (an array, a vector, etc)."]}),"\n",(0,i.jsx)(n.h3,{id:"fixing-lock-consistency-violation-reports",children:"Fixing Lock Consistency Violation reports"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Avoid the offending access (most often the read). Of course, this may not be\npossible."}),"\n",(0,i.jsx)(n.li,{children:"Use synchronization to protect the read, by using the same lock protecting the\ncorresponding write."}),"\n",(0,i.jsx)(n.li,{children:"Make the method doing the read access private. This should silence the\nwarning, since Infer looks for a pair of non-private methods. Objective-C:\nInfer considers a method as private if it's not exported in the header-file\ninterface."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"logging_private_data",children:"LOGGING_PRIVATE_DATA"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Logging Private Data" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_c",children:"MEMORY_LEAK_C"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-c",children:"Memory leak in C"}),"\n",(0,i.jsx)(n.p,{children:"This error type is only reported in C and Objective-C code. In Java we do not\nreport memory leaks because it is a garbage collected language."}),"\n",(0,i.jsxs)(n.p,{children:["In C, Infer reports memory leaks when objects are created with ",(0,i.jsx)(n.code,{children:"malloc"})," and not\nfreed. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"-(void) memory_leak_bug {\n struct Person *p = malloc(sizeof(struct Person));\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-objective-c",children:"Memory leak in Objective-C"}),"\n",(0,i.jsx)(n.p,{children:"Additionally, in Objective-C, Infer reports memory leaks that happen when\nobjects from Core Foundation or Core Graphics don't get released."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) memory_leak_bug_cf {\n CGPathRef shadowPath = CGPathCreateWithRect(self.inputView.bounds, NULL); //object created and not released.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_cpp",children:"MEMORY_LEAK_CPP"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"})]}),"\n",(0,i.jsx)(n.h2,{id:"missing_required_prop",children:"MISSING_REQUIRED_PROP"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Missing Required Prop" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-litho-required-props",children:"litho-required-props"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issues is reported when a required ",(0,i.jsx)(n.code,{children:"@Prop"})," is missing."]}),"\n",(0,i.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,i.jsxs)(n.p,{children:["Assume that the following Litho Component specification is defined as follows where ",(0,i.jsx)(n.code,{children:"prop1"})," is optional and ",(0,i.jsx)(n.code,{children:"prop2"})," is required."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n static void onCreate(\n ComponentContext c,\n @Prop(optional = true) String prop1, @Prop int prop2) {\n ...\n }\n ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["When we build the corresponding component, we should have all the required props. If we are missing optional props (e..g ",(0,i.jsx)(n.code,{children:"prop1"})," below), it is ok."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"MyComponent.create(c)\n .prop2(8)\n .build();\n"})}),"\n",(0,i.jsxs)(n.p,{children:["However, if we are missing a required prop, Infer gives an error below for the missing ",(0,i.jsx)(n.code,{children:"prop2"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .build();\n'})}),"\n",(0,i.jsx)(n.p,{children:"** Action **"}),"\n",(0,i.jsx)(n.p,{children:"There are two ways to fix this issue."}),"\n",(0,i.jsxs)(n.p,{children:["First, we could add the missing ",(0,i.jsx)(n.code,{children:"prop2"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .prop2(x) // where x is some integer\n .build();\n'})}),"\n",(0,i.jsxs)(n.p,{children:["or alternatively, if the ",(0,i.jsx)(n.code,{children:"prop2"})," is not really required, we could change the component spec to reflect that:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n static void onCreate(\n ComponentContext c,\n @Prop(optional = true) String prop1, @Prop(optional = true) int prop2) {\n ...\n }\n ...\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Mixed Self WeakSelf" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports an issue when an Objective-C block captures both ",(0,i.jsx)(n.code,{children:"self"})," and ",(0,i.jsx)(n.code,{children:"weakSelf"}),", a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),".\nPossibly the developer meant to capture only ",(0,i.jsx)(n.code,{children:"weakSelf"})," to avoid a retain cycle, but made a typo and used ",(0,i.jsx)(n.code,{children:"self"}),"\ninstead of ",(0,i.jsx)(n.code,{children:"strongSelf"}),". In this case, this could cause a retain cycle."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n int x = self->x; // typo here\n }\n return 0;\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),": Fixing the typo is generally the right course of action."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"modifies_immutable",children:"MODIFIES_IMMUTABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Modifies Immutable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue type indicates modifications to fields marked as @Immutable. For instance, below function ",(0,i.jsx)(n.code,{children:"mutateArray"})," would be marked as modifying immutable field ",(0,i.jsx)(n.code,{children:"testArray"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" @Immutable int[] testArray = new int[]{0, 1, 2, 4};\n \n int[] getTestArray() {\n return testArray;\n } \n \n void mutateArray() {\n int[] array = getTestArray();\n array[2] = 7;\n }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"multiple_weakself",children:"MULTIPLE_WEAKSELF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Multiple WeakSelf Use" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when an Objective-C block uses ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),") more than once.\nThis could lead to unexpected behaviour. Even if ",(0,i.jsx)(n.code,{children:"weakSelf"})," is not nil in the first use, it could be nil\nin the following uses since the object that ",(0,i.jsx)(n.code,{children:"weakSelf"})," points to could be freed anytime."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n [weakSelf foo];\n int x = weakSelf->x;\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nOne should assign ",(0,i.jsx)(n.code,{children:"weakSelf"})," to a strong pointer first, and then\nuse it in the block."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n int x = strongSelf->x;\n }\n ...\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call",children:"NIL_BLOCK_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Block Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when one tries to call an Objective-C block that is ",(0,i.jsx)(n.code,{children:"nil"}),".\nThis causes a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) foo:(void (^)())callback {\n callback();\n}\n\n-(void) bar {\n [self foo:nil]; //crash\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling the block, or making sure never to call the method ",(0,i.jsx)(n.code,{children:"foo:"})," with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Block Call Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_block_call",children:"NIL_BLOCK_CALL"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports when ",(0,i.jsx)(n.code,{children:"nil"})," is passed to collections in Objective-C such as arrays and dictionaries. This causes a crash."]}),"\n",(0,i.jsx)(n.h3,{id:"arrays",children:"Arrays"}),"\n",(0,i.jsxs)(n.p,{children:["Adding objects to an array, inserting objects at a given index, or replacing objects at a given index, can all\nlead to a crash when the object is ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" [mArray addObject:nil]; //crash\n\n [mArray insertObject:nil atIndex:0]; //crash\n\n [mArray replaceObjectAtIndex:0 withObject:nil]; //crash\n"})}),"\n",(0,i.jsx)(n.h3,{id:"dictionaries",children:"Dictionaries"}),"\n",(0,i.jsxs)(n.p,{children:["Adding a ",(0,i.jsx)(n.code,{children:"nil"})," value in a dictionary causes a crash. If the concept of ",(0,i.jsx)(n.code,{children:"nil"})," is required, one can add\n",(0,i.jsx)(n.code,{children:"[NSNull null]"})," instead."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' id value = nil;\n [mDict setObject:value forKey:@"somestring"]; //crash\n\n [mDict setObject:[NSNull null] forKey:@"somestring"]; //ok\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Retrieving or removing an object from a dictionary with a ",(0,i.jsx)(n.code,{children:"nil"})," key also causes a crash:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' id key = nil;\n mDict[key] = @"somestring"; //crash\n\n [mDict removeObjectForKey:nil]; //crash\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["In all the cases above, when passing ",(0,i.jsx)(n.code,{children:"nil"})," causes a crash, the solutions are either making sure\nthat the object passed will never be ",(0,i.jsx)(n.code,{children:"nil"}),", or adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling those methods."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Messaging To Non Pod" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, calling a method on ",(0,i.jsx)(n.code,{children:"nil"})," (or in Objective-C terms, sending a message to ",(0,i.jsx)(n.code,{children:"nil"}),") does not crash,\nit simply returns a falsy value (nil/0/false). However, sending a message that returns\na non-POD C++ type (POD being ",(0,i.jsx)(n.a,{href:"https://en.cppreference.com/w/cpp/named_req/PODType",children:'"Plain Old Data"'}),", essentially\nanything that cannot be compiled as a C-style struct) to ",(0,i.jsx)(n.code,{children:"nil"})," causes undefined behaviour."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr callMethodReturnsnonPOD() {\n SomeObject* obj = getObjectOrNil();\n std::shared_ptr d = [obj returnsnonPOD]; // UB\n return d;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["To fix the above issue, we need to check if ",(0,i.jsx)(n.code,{children:"obj"})," is\nnot ",(0,i.jsx)(n.code,{children:"nil"})," before calling the ",(0,i.jsx)(n.code,{children:"returnsnonPOD"})," method:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr callMethodReturnsnonPOD(bool b) {\n SomeObject* obj = getObjectOrNil(b);\n if (obj == nil) { return std::make_shared(0); }\n std::shared_ptr d = [obj returnsnonPOD];\n return d;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Messaging To Non Pod Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Branch In Try" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching branch is found when evaluating the ",(0,i.jsx)(n.code,{children:"of"})," section of a ",(0,i.jsx)(n.code,{children:"try"})," expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{try_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n try X of\n [_|T] -> {ok,T}\n catch\n _ -> error\n end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Branch In Try Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Case Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching case clause in Erlang: Reports an error when none of the clauses of a ",(0,i.jsx)(n.code,{children:"case"})," match the expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{case_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n case X of\n [_|T] -> T\n end.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Case Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Function Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching function clause in Erlang: Reports an error when none of the clauses of a function match the arguments of a call. Corresponds to the ",(0,i.jsx)(n.code,{children:"function_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail([_|Xs]) -> Xs.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Function Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Match Of Rhs" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No match of right hand side value in Erlang: Reports an error when the right hand side value of a ",(0,i.jsx)(n.code,{children:"match"})," expression does not match the pattern on the left hand side. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badmatch,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, ",(0,i.jsx)(n.code,{children:"[H|T] = []"})," gives the error because the left hand side pattern requires at least one element in the list on the right hand side."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Match Of Rhs Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No True Branch In If" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No true branch when evaluating an if expression in Erlang: Reports an error when none of the branches of an ",(0,i.jsx)(n.code,{children:"if"})," expression evaluate to true. Corresponds to the ",(0,i.jsx)(n.code,{children:"if_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"sign(0)"})," and the full definition of ",(0,i.jsx)(n.code,{children:"sign"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"sign(X) ->\n if\n X > 0 -> positive;\n X < 0 -> negative\n end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No True Branch In If Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" p = foo(); // foo() might return null\n stuff();\n p.goo(); // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n //... intervening code\n\n p = checkNotNull(foo()); // foo() might return null\n stuff();\n p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n int age;\n int height;\n int weight;\n};\nint get_age(struct Person *who) {\n return who->age;\n}\nint null_pointer_interproc() {\n struct Person *joe = 0;\n return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param { // passing nil\n D* d = [param bar]; // nil message passing\n return d->fld; // crash\n}\n(void) callFoo {\n C* c = [self bar]; // returns nil\n [foo:c]; // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java-1",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" p = foo(); // foo() might return null\n stuff();\n p.goo(); // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n //... intervening code\n\n p = checkNotNull(foo()); // foo() might return null\n stuff();\n p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c-1",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n int age;\n int height;\n int weight;\n};\nint get_age(struct Person *who) {\n return who->age;\n}\nint null_pointer_interproc() {\n struct Person *joe = 0;\n return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c-1",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param { // passing nil\n D* d = [param bar]; // nil message passing\n return d->fld; // crash\n}\n(void) callFoo {\n C* c = [self bar]; // returns nil\n [foo:c]; // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"null_argument",children:"NULL_ARGUMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Argument" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"This issue type indicates `nil` being passed as argument where a non-nil value expected.\n\n#import \n\n// Test (non-nil) returned values of NSString methods against `nil`\nNSString* stringNotNil(NSString* str) {\n if (!str) {\n // ERROR: NSString:stringWithString: expects a non-nil value\n\treturn [NSString stringWithString:nil];\n }\n return str;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"null_argument_latent",children:"NULL_ARGUMENT_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Argument Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#null_argument",children:"NULL_ARGUMENT"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"null_dereference",children:"NULL_DEREFERENCE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" 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:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Optional Empty Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Optional Empty Access warnings are reported when we try to retrieve the value of a ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/folly/blob/master/folly/Optional.h",children:(0,i.jsx)(n.code,{children:"folly::Optional"})})," when it is empty (i.e. ",(0,i.jsx)(n.code,{children:"folly::none"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:["In the following example we get a warning as ",(0,i.jsx)(n.code,{children:"int_opt"})," might be ",(0,i.jsx)(n.code,{children:"folly::none"})," and its value is being accessed:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v);\n\nfolly::Optional mightReturnNone(int v) {\n if (somef(v)) {\n return folly::Optional(v);\n }\n\n return folly::none;\n}\n\nint value_no_check() {\n folly::Optional int_opt = mightReturnNone (4);\n return int_opt.value(); // Optional Empty Access warning\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["We do not get the warning anymore if we add a check whether ",(0,i.jsx)(n.code,{children:"int_opt"})," is not empty:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"int value_check() {\n folly::Optional int_opt = mightReturnNone (4);\n if (int_opt.has_value()) {\n return int_opt.value(); // OK\n }\n return -1;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"In some cases we know that we have a non-empty value and there is no need to have a check. Consider the following example where Infer does not warn:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v) {return v > 3;};\n\nfolly::Optional mightReturnNone(int v) {\n if (somef(v)) {\n return folly::Optional(v);\n }\n\n return folly::none;\n}\n\nint value_no_check() {\n folly::Optional int_opt = mightReturnNone (4); // cannot be folly::none\n return int_opt.value(); // OK\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Optional Empty Access Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"premature_nil_termination_argument",children:"PREMATURE_NIL_TERMINATION_ARGUMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Premature Nil Termination Argument" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error type is reported in C and Objective-C. In many variadic methods,\n",(0,i.jsx)(n.code,{children:"nil"})," is used to signify the end of the list of input objects. This is similar\nto nil-termination of C strings. If one of the arguments that is not the last\nargument to the method is ",(0,i.jsx)(n.code,{children:"nil"})," as well, Infer reports an error because that may\nlead to unexpected behavior."]}),"\n",(0,i.jsxs)(n.p,{children:["An example of such variadic methods is\n",(0,i.jsx)(n.a,{href:"https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/index.html#//apple_ref/occ/clm/NSArray/arrayWithObjects",children:"arrayWithObjects"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' NSArray *foo = [NSArray arrayWithObjects: @"aaa", str, @"bbb", nil];\n'})}),"\n",(0,i.jsxs)(n.p,{children:["In this example, if ",(0,i.jsx)(n.code,{children:"str"})," is ",(0,i.jsx)(n.code,{children:"nil"})," then an array ",(0,i.jsx)(n.code,{children:'@[@"aaa"]'})," of size 1 will be\ncreated, and not an array ",(0,i.jsx)(n.code,{children:'@[@"aaa", str, @"bbb"]'})," of size 3 as expected."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_const_refable",children:"PULSE_CONST_REFABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Const Refable Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a function parameter is a) passed by value and b) is not modified inside the function. Instead, parameter can be passed by const reference, i.e. converted to a ",(0,i.jsx)(n.code,{children:"const&"})," so that no unnecessary copy is created at the callsite of the function."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include \n\nint read_first(const std::vector& vec) { return vec[0]; }\n\nvoid const_refable(std::vector vec) {\n int first = read_first(vec); // vec is never modified, so the parameter should have type const&\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Read-only Shared Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a shared pointer parameter is a) passed by value and b) is used only for reading, rather than lifetime extension. At the callsite, this might cause a potentially expensive unnecessary copy of the shared pointer, especially when many number of threads are sharing it. To avoid this, consider 1) passing the raw pointer instead and 2) use ",(0,i.jsx)(n.code,{children:"std::shared_ptr::get"})," at callsites."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(std::shared_ptr x) {\n // read_T(*x);\n}\n\nvoid caller() {\n callee(shared_ptr);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"can be changed to"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(T* p) {\n // read_T(*p);\n}\n\nvoid caller() {\n callee(shared_ptr.get());\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Reference Stability" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The family of maps ",(0,i.jsx)(n.code,{children:"folly::F14ValueMap"}),", ",(0,i.jsx)(n.code,{children:"folly::F14VectorMap"}),", and by extension\n",(0,i.jsx)(n.code,{children:"folly::F14FastMap"})," differs slightly from ",(0,i.jsx)(n.code,{children:"std::unordered_map"})," as it does not\nprovide reference stability. When the map resizes such as when ",(0,i.jsx)(n.code,{children:"reserve"})," is\ncalled or new elements are added, all existing references become invalid and\nshould not be used."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"operator[]"})," is an interesting case as it can easily introduce unsafe code when\nused twice in the same expression. Depending on what keys are present and which\norder the compiler sequences sub-expressions, an insert via ",(0,i.jsx)(n.code,{children:"operator[]"})," can\ninvalidate a reference obtained in the same expression before it's read from.\nTypically, those cases can be improved by using other map functions such as\n",(0,i.jsx)(n.code,{children:"at"}),", ",(0,i.jsx)(n.code,{children:"find"}),", ",(0,i.jsx)(n.code,{children:"emplace"}),", or ",(0,i.jsx)(n.code,{children:"insert_or_assign"})," to increase code quality and\nsafety."]}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include \n\nvoid use_reference_after_growth_bad(folly::F14FastMap& map) {\n const auto& valueRef = map.at(1);\n map.emplace(13, 71);\n const auto valueCopy = valueRef;\n}\n\nvoid unsafe_expressions_bad(folly::F14FastMap& map) {\n // Unsafe expressions in situations where one or both keys are not present.\n map[13] = map[71];\n const auto p = map[13] * map[71];\n const auto q = f(map[13], map[71]);\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#resource_leak",children:"RESOURCE_LEAK"})]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Transitive Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue tracks spurious accesses that are reachable from specific entry functions."}),"\n",(0,i.jsx)(n.p,{children:"Spurious accesses are specified as specific load/calls."}),"\n",(0,i.jsx)(n.p,{children:"Entry functions are specified through their enclosing class that must extend a specific\nclass and should not extend a list of specific classes."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unawaited Awaitable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Awaitable"})," values created by calls to asynchronous methods should eventually be ",(0,i.jsx)(n.code,{children:"await"}),"ed along all codepaths (even if their value is unused). Hence the following is ",(0,i.jsx)(n.em,{children:"not"})," OK"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"class A {\n public static async genInt() : Awaitable{\n // typically do something involving IO\n }\n\n public static async genBad() : Awaitable {\n $_unused = self::genInt(); // ERROR: should have done $_unused = await self::genInt();\n return;\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Failure to ",(0,i.jsx)(n.code,{children:"await"})," an ",(0,i.jsx)(n.code,{children:"Awaitable"})," can lead to non-deterministic amount of the asynchronous call actually being executed, and can also indicate a logical confusion between ",(0,i.jsx)(n.code,{children:"T"})," and ",(0,i.jsx)(n.code,{children:"Awaitable"})," that may not be caught by the type-checker."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsxs)(n.a,{href:"#uninitialized_value",children:[(0,i.jsx)(n.code,{children:"UNINITIALIZED_VALUE"})," issue"]}),", but it is to detect the uninitialized abstract const value in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the ",(0,i.jsx)(n.code,{children:"FIELD"})," can be read by the static method ",(0,i.jsx)(n.code,{children:"get_field"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["It is problematic invoking ",(0,i.jsx)(n.code,{children:"static::FIELD"}),", since it may be resolved to a ",(0,i.jsx)(n.code,{children:"A::FIELD"})," access, if called from ",(0,i.jsx)(n.code,{children:"A::get_field()"}),". Because ",(0,i.jsx)(n.code,{children:"FIELD"})," is abstract in ",(0,i.jsx)(n.code,{children:"A"}),", it is never assigned a value and the vm will crash. Unfortunately, Hack's type system cannot catch this."]}),"\n",(0,i.jsxs)(n.li,{children:["In the ",(0,i.jsx)(n.code,{children:"B"})," class, ",(0,i.jsx)(n.code,{children:"FIELD"})," is initialized, thus invoking ",(0,i.jsx)(n.code,{children:"B::get_field"})," is safe."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:'abstract class A {\n abstract const string FIELD;\n \n public static function get_field(): string {\n return static::FIELD;\n }\n}\n\nfunction call_get_field_bad(): string {\n return A::get_field();\n}\n\nclass B extends A {\n const string FIELD = "defined";\n}\n\nfunction call_get_field_ok(): string {\n return B::get_field();\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#uninitialized_value",children:"UNINITIALIZED_VALUE"}),". Re-implemented using Pulse."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_value_latent",children:"PULSE_UNINITIALIZED_VALUE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" 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:"#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy of an object via copy constructor where neither the source nor the copied variable are modified before the variable goes out of scope. Rather than the copy, a reference to the source object could be used to save memory."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n int a;\n};\n\nint unnecessary_copy(A& x){\n auto y = x; // calls copy constructor\n return y.a; // y is not modified after copy, hence we could avoid the copy by adding & after auto as below\n}\n\nint use_reference_instead(A& x){\n auto& y = x; // copy the ref only\n return y.a;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Intermediate" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary temporary copy of an intermediate object where copy is created to be passed down to a function unnecessarily. Instead, the intermediate object should either be moved into the callee or the type of the callee's parameter should be made ",(0,i.jsx)(n.code,{children:"const &"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A prime example of this occurs when we call a function with a call-by-value parameter as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(ExpensiveObject obj) {\n // ....\n}\n\nvoid caller() {\n callee(myExpensiveObj); // a copy of myExpensiveObj is created\n // the copy is destroyed right after the call \n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this case, when we call ",(0,i.jsx)(n.code,{children:"callee"}),", under the hood, a copy of the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is created to be passed to the function call. However, the copy might be unnecessary if"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"callee"})," doesn\u2019t modify its parameter \u2192 then we can change its type to ",(0,i.jsx)(n.code,{children:"const ExpensiveObject&"}),", getting rid of the copy at caller"]}),"\n",(0,i.jsxs)(n.li,{children:["even if ",(0,i.jsx)(n.code,{children:"callee"})," might modify the object, if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is never used later on, we can get rid of the copy by moving it instead: ",(0,i.jsx)(n.code,{children:"callee(std::move(myExpensiveObj))"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The analysis is careful about suggesting moves blindly though: if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is of type ",(0,i.jsx)(n.code,{children:"const & ExpensiveObject"})," then we also recommend that for move to work, const-reference needs to be removed."]}),"\n",(0,i.jsx)(n.p,{children:"PS: We check for other conditions on the argument here: e.g. it should be local to the procedure, as moving a non-local member might cause other memory correctness issues like use-after-move later on."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Intermediate from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy into a field where"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the source is an rvalue-reference"}),"\n",(0,i.jsx)(n.li,{children:"the source is not modified before it goes out of scope or is destroyed."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that the copy can be modified since it has the ownership of the object."}),"\n",(0,i.jsx)(n.p,{children:"Fix: Rather than the copying into the field, the source should be moved into it."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n std::vector vec;\n};\n\nclass Test {\n A mem_a;\n\n void unnecessary_copy(A&& src) {\n mem_a = src;\n // fix is to move as follows\n // mem_a = std::move(src);\n }\n\n};\n\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy to Optional" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary copy of an object via ",(0,i.jsx)(n.code,{children:"optional"})," value\nconstruction where the source is not modified before it goes out of scope. To avoid the copy, we\ncan move the source object or change the callee's type."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void get_optional_value(std::optional x) {}\n\nvoid pass_non_optional_value(A x) {\n get_optional_value(x);\n // fix is to move as follows\n // get_optional_value(std::move(x));\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy to Optional from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Return" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is similar to ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),", but reported when a callee returns a copied value and it is not modified in its caller. We may be able to return const-ref typed value or try ",(0,i.jsx)(n.code,{children:"std::move"})," to avoid the copy."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"class MyClass {\n T v;\n public:\n T get() {\n return v; // v is copied here, which is avoidable.\n }\n};\n\nvoid caller(MyClass obj) {\n T x = obj.get();\n std::cout << x; // x is not modified.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pure_function",children:"PURE_FUNCTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Pure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-purity",children:"purity"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates pure functions. For instance, below functions would be marked as pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int local_write_pure(int x, int y) {\n int k = x + y;\n k++;\n return k;\n}\n\n// no change to outside state, the local allocation is ok.\nint local_alloc_pure(ArrayList list) {\n ArrayList list_new = new ArrayList();\n for (Integer el : list) {\n list_new.add(el);\n }\n return list_new.size();\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"However, the following ones would not be pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void swap_impure(int[] array, int i, int j) {\n int tmp = array[i];\n array[i] = array[j]; // modifying the input array\n array[j] = tmp;\n}\n\nint a = 0;\nvoid set_impure(int x, int y) {\n a = x + y; //modifying a global variable\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"quandary_taint_error",children:"QUANDARY_TAINT_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Taint Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Generic taint error when nothing else fits."}),"\n",(0,i.jsx)(n.h2,{id:"regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Regex Op On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A potentially costly operation on a regular expression occurs on the UI thread."}),"\n",(0,i.jsx)(n.h2,{id:"resource_leak",children:"RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports resource leaks in C, Objective-C and Java. In general, resources\nare entities such as files, sockets, connections, etc, that need to be closed\nafter being used."}),"\n",(0,i.jsx)(n.h3,{id:"resource-leak-in-c",children:"Resource leak in C"}),"\n",(0,i.jsx)(n.p,{children:"This is an example of a resource leak in C code:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:'-(void) resource_leak_bug {\n FILE *fp;\n fp=fopen("c:\\\\test.txt", "r"); // file opened and not closed.\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"resource-leak-in-java",children:"Resource leak in Java"}),"\n",(0,i.jsx)(n.p,{children:"For the remaining of this section, we will consider examples of resource leaks\nin Java code."}),"\n",(0,i.jsxs)(n.p,{children:["TIP: A common source of bugs is ",(0,i.jsx)("b",{children:"exceptions skipping past close()\nstatements"}),". That is the first thing to look for if INFER reports a potential\nresource leak."]}),"\n",(0,i.jsx)(n.h3,{id:"basics-and-standard-idiom",children:"Basics and Standard Idiom"}),"\n",(0,i.jsxs)(n.p,{children:["Some objects in Java, the ",(0,i.jsx)("i",{children:"resources"}),", are supposed to be closed when you\nstop using them, and failure to close is a ",(0,i.jsx)("i",{children:"resource leak"}),". Resources\ninclude input streams, output streams, readers, writers, sockets, http\nconnections, cursors, and json parsers."]}),"\n",(0,i.jsx)(n.p,{children:"The standard idiom is"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // Standard idiom\n Allocate resource\n try {\n do some stuff\n } finally {\n close resource\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"or more for example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Standard Idiom\n public static void foo () throws IOException{\n FileOutputStream fos = new FileOutputStream(new File("whatever.txt"));\n try {\n fos.write(7);\n } finally {\n fos.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"and you should use the standard idiom for the most part, when you don't want to\nreturn the resource to the surrounding context."}),"\n",(0,i.jsx)(n.p,{children:"Sometimes people just leave out close(), and that is a bug, but more typically\nexceptional paths are the root of the problem, as in"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // leak because of exception\n public static void foo () throws IOException {\n FileOutputStream fos = new FileOutputStream(new File("whatever.txt"));\n fos.write(7); //DOH! What if exception?\n fos.close();\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"where an exception in fos.write will cause execution to skip past the close()\nstatement."}),"\n",(0,i.jsx)(n.h4,{id:"multiple-resources-bugs",children:"Multiple Resources Bugs"}),"\n",(0,i.jsx)(n.p,{children:"We can deal with multiple resources correctly and simply just by nesting the\nstandard idiom."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources nested\n public static void foo() throws IOException {\n FileInputStream fis = new FileInputStream(new File("whatever.txt"));\n try {\n FileOutputStream fos = new FileOutputStream(new File("everwhat.txt"));\n try {\n fos.write(fis.read());\n } finally {\n fos.close();\n }\n } finally {\n fis.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"Bugs often occur when using multiple resources in other ways because of\nexceptions in close() methods. For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Classic Two Resources Bug\n public static void foo() throws IOException {\n FileInputStream fis = null;\n FileOutputStream fos = null;\n try {\n fis = new FileInputStream(new File("whatever.txt"));\n fos = new FileOutputStream(new File("everwhat.txt"));\n fos.write(fis.read());\n } finally {\n if (fis!=null) fis.close();\n if (fos!=null) fos.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"Here, if there is an exception in the call to fis.close() execution will skip\npast fos.close(); a leak."}),"\n",(0,i.jsx)(n.p,{children:"Another way, besides the standard idiom, to deal with this problem is to swallow\nexceptions."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources Fix 1\n public static void foo() throws IOException {\n FileInputStream fis = null;\n FileOutputStream fos = null;\n try {\n fis = new FileInputStream(new File("whatever.txt"));\n fos = new FileOutputStream(new File("everwhat.txt"));\n fos.write(fis.read());\n } finally {\n try {\n if (fis!=null) fis.close();\n } catch (Exception e) {}; // Exception swallowing\n if (fos!=null) fos.close();\n }\n }\n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can also swallow the exception on the output stream. Some people prefer not\nto swallow output stream exceptions, and also flush before closing.\n",(0,i.jsx)(n.a,{href:"http://code.google.com/p/guava-libraries/issues/detail?id=1118",children:"http://code.google.com/p/guava-libraries/issues/detail?id=1118"})]}),"\n",(0,i.jsx)(n.p,{children:"Notice that the nested standard idiom does not need the checks for null, which\nare in there in this case to protect against the case when one of the\nallocations throws an exception, in which case one would get a\nNullPointerException."}),"\n",(0,i.jsx)(n.h3,{id:"nested_allocations",children:"Nested_Allocations"}),"\n",(0,i.jsx)(n.p,{children:"When a resource allocation is included as an argument to a constructor, if the\nconstructor fails it can leave an unreachable resource that no one can close."}),"\n",(0,i.jsx)(n.p,{children:"For example gzipOutputStream = new GZIPOutputStream(new FileOutputStream(out));\nis bad in case the outer constructor, GZIPOutputStream, throws an exception. In\nthat case, no one will have a hold of the FileOutputStream and so no one will be\nable to close it."}),"\n",(0,i.jsx)(n.p,{children:"In such a case you need to move the allocation the FileOutputStream out of the\nnested position and name it, so you are able to close if anything goes wrong\nduring execution of the GZIPOutputStream constructor."}),"\n",(0,i.jsx)(n.p,{children:"Here are resources that can throw exceptions i their constructor(s)."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"ObjectInputStream , ObjectOutputStream, PipedInputStream, PipedOutputStream,\nPipedReader, PipedWriter, JarInputStream, JarOutputStream, GZIPInputStream,\nGZIPOutputStream , ZipFile all throw IOException"}),"\n",(0,i.jsx)(n.li,{children:"PrintStream throws UnsupportedEncodingException"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The constructors for FileInputStream, FileOutputStream and RandomAccessFile\nthrow FileNotFoundException, but these cases are not problematic in the sense\nthat their arguments are not resources and so they do not cause the nested\nresource leak."}),"\n",(0,i.jsx)(n.h3,{id:"allocation-of-jsonparser-and-cursor-resources",children:"Allocation of JSonParser and Cursor resources"}),"\n",(0,i.jsx)(n.p,{children:'Some resources are created inside libraries instead of by "new".'}),"\n",(0,i.jsx)(n.p,{children:"Cursor is an interface, the actual resources are something like SQLiteCursor.\nSo, every time you call a function that returns a Cursor object, there is an\nallocation."}),"\n",(0,i.jsx)(n.p,{children:"For instance, in the functions from SQLiteDatabase query(\u2026) and rawQuery(\u2026)\nallocate a cursor resource. For SQLiteQueryBuilder, ContentProviderClient,\nContentResolver. MediaStore and DownloadManager it is only query(\u2026) Cursor\nobjects cursor created by these functions need to be closed (i.e.,\ncursor.close())."}),"\n",(0,i.jsx)(n.p,{children:"Similarly, JsonParser is an abstract class, and create a resource in functions\nfrom the class JsonFactory createParser(byte[] data) createParser(byte[] data,\nint offset, int len) createParser(String content) createParser(URL url)\ncreateParser(File f) JsonParser objects js created by these functions need to be\nclosed (jp.close()). On the other hand . JasonParsers gotten from\ncreateParser(InputStream in) and createParser(Reader r) give you JsonParsers\nthat don\u2019t need to be closed. This is because they receive the resource from\nsomewhere that will maintain the responsibility to close it."}),"\n",(0,i.jsx)(n.h3,{id:"escaping-resources-and-exceptions",children:"Escaping resources and exceptions"}),"\n",(0,i.jsx)(n.p,{children:"Sometimes you want to return a resource to the outside, in which case you should\nnot close it, but you still need to be careful of exceptions in case control\nskips past the return leaving no one to close. Here is a simple example of a\npositive use of escaping resources."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // An escaping resource, shouldn't close\n public BugReportAttachment createAttachment(File reportDirectory, String fileName)\n throws FileNotFoundException {\n File file = new File(reportDirectory, fileName);\n OutputStream stream = new FileOutputStream(file);\n return new BugReportAttachment(Uri.fromFile(file), stream);\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this case it is intended that an object that wraps ",(0,i.jsx)(n.code,{children:"stream"})," is passed to the\ncaller of ",(0,i.jsx)(n.code,{children:"createAttachment"}),". You should certainly not close stream here,\nbecause it is being passed to the outside."]}),"\n",(0,i.jsx)(n.p,{children:"But for escaping resources like this you still need to be careful of exceptions.\nFor example, in"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // An escaping resource, and a leak\n public BugReportAttachment createAttachment(File reportDirectory, String fileName)\n throws FileNotFoundException {\n File file = new File(reportDirectory, fileName);\n OutputStream stream = new FileOutputStream(file);\n stream.write(7);\n return new BugReportAttachment(Uri.fromFile(file), stream);\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"if stream.write(7) throws an exception, then no one will have a hold of stream,\nand no one will be able to close it; a leak."}),"\n",(0,i.jsx)(n.h3,{id:"java-7s-try-with-resources",children:"Java 7's try-with-resources"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"(For use with Java 7 only)"})}),"\n",(0,i.jsx)(n.p,{children:"Clearly, accounting for the ramifications of all the exceptional cases is\ncomplicated, and there is a better way in Java 7."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources Fix 2; via try-with-resources\n public static void foo() throws IOException {\n try (\n FileInputStream fis = new FileInputStream(new File("whatever.txt"));\n FileOutputStream fos = new FileOutputStream(new File("everwhat.txt"))\n ) {\n fos.write(fis.read());\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"All the complicated exceptional cases above are (apparently) covered by this\nconstruct, and the result is much simpler."}),"\n",(0,i.jsx)(n.p,{children:"So, if you are trying to fix a potential leak in code with multiples resources\nyou can go ahead and try to understand whether the potential leak is real. Or,\nif the code is complex and it is hard to figure out, it would be perfectly\nlegitimate to simply convert the code over to try-with-resources if you have\naccess to Java 7, so as to save yourself some brain-cycles. You will also end up\nwith cleaner code."}),"\n",(0,i.jsxs)(n.p,{children:["If try-with-resources is so great you should ",(0,i.jsx)("i",{children:"always"}),' use it. But you\nshouldn\'t\u2026 Try-with-resources gives resources static scoping, and works via a\nstack discipline. Sometimes, you want a resource to persist beyond scope, as in\nthe escaping example above. In an escaping example maybe you could refactor lots\nof code so that try-with-resources applies, and maybe you cannot in a sensible\nway. This just illustrates that, though you might hear people say that\ntry-with-resources "solves" the resource problem, it does not. It is very\nuseful, but you cannot use it blindly when you see a resource-allocation site.']}),"\n",(0,i.jsx)(n.h2,{id:"retain_cycle",children:"RETAIN_CYCLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Retain Cycle" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A retain cycle is a situation when object A retains object B, and object B\nretains object A at the same time. Here is an example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n Child *child; // Instance variables are implicitly __strong\n}\n@end\n@interface Child : NSObject {\n Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.p,{children:'You can fix a retain cycle in ARC by using __weak variables or weak properties\nfor your "back links", i.e. links to direct or indirect parents in an object\nhierarchy:'}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n Child *child;\n}\n@end\n@interface Child : NSObject {\n __weak Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.h2,{id:"scope_leakage",children:"SCOPE_LEAKAGE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Scope Leakage" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-scope-leakage",children:"scope-leakage"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'This issue type indicates that a class with scope annotation A stores a field\nwith whose (dynamic) type (or one of its super types) is annotated with scope\nB such that a scope nesting restriction is violated. By "stores", we mean\neither directly or transitively.'}),"\n",(0,i.jsx)(n.p,{children:"A configuration is used to list the set of scopes and the must-not-hold relation."}),"\n",(0,i.jsx)(n.p,{children:"In the following Java example, the set of scopes is Outer and Inner, and the must-not-hold\nrelation is simply {(Outer, Inner)}:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@ScopeType(value = Outer.class)\nclass ClassOfOuterScope {\n final ClassOfInner c = new ClassOfInner(); // <-- warn here that ClassOfInner would leak.\n}\n\n@ScopeType(value = Inner.class)\nclass ClassOfInner {}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Here is a more detailed description of the analysis."}),"\n",(0,i.jsx)(n.p,{children:'This analysis operates over Java bytecode. It assumes that types (classes, interfaces, enums,\netc.) may be annotated with so-called scope annotations. The analysis is parameterized by a set\nof scopes and a "must-not-hold" relation over pairs of scopes, which it reads from a\nconfiguration file.'}),"\n",(0,i.jsx)(n.p,{children:'The analysis aims to detect violations of the following property: if there exist a path of\nfields from object OA to object OB and the type of OA (or one of its super-types) is annotated\nwith scope SA and the type of OB (or one of its super-types) is annotated with scope SB then\nmust-not-hold(SA, SB) must be false. Intuitively, the given objects have different scopes that\nshould not be nested, for example, different intended lifetimes, and a forbidden path from OA to\nOB results in OB "leaking" out of the scope SA.'}),"\n",(0,i.jsx)(n.p,{children:'The implementation reads a configuration to determine a list of (scope) "generators" for each\ntype of scope and a scope class for each type of scope. A generator for a scope type SA is given\nby the name of a class and a list of methods where it is understood that any of the methods\nlisted for the given class returns an object that is known to have scope SA. (This can be seen\nas a form of lightweight modeling.) A scope class is the name of the class that represents a\ngiven scope.'}),"\n",(0,i.jsx)(n.h2,{id:"sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sensitive Data Flow" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A flow of sensitive data was detected from a source."}),"\n",(0,i.jsx)(n.h2,{id:"shell_injection",children:"SHELL_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Shell Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Environment variable or file data flowing to shell."}),"\n",(0,i.jsx)(n.h2,{id:"shell_injection_risk",children:"SHELL_INJECTION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Shell Injection Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Code injection if the caller of the endpoint doesn't sanitize on its end."}),"\n",(0,i.jsx)(n.h2,{id:"sql_injection",children:"SQL_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sql Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted and unescaped data flows to SQL."}),"\n",(0,i.jsx)(n.h2,{id:"sql_injection_risk",children:"SQL_INJECTION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sql Injection Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted and unescaped data flows to SQL."}),"\n",(0,i.jsx)(n.h2,{id:"stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Stack Variable Address Escape" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Reported when an address pointing into the stack of the current\nfunction will escape to its calling context. Such addresses will\nbecome invalid by the time the function actually returns so are\npotentially dangerous."}),"\n",(0,i.jsx)(n.p,{children:"For example, directly returning a pointer to a local variable:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-C",children:'int* foo() {\n int x = 42;\n return &x; // <-- warn here that "&x" will escape\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"starvation",children:"STARVATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "UI Thread Starvation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This error is reported in Java, and specifically on Android. These reports are\ntriggered when a method that runs on the UI thread may block, thus potentially\nleading to an Application Not Responding error."}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The issue is reported when a method deemed to run on the UI thread"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Makes a method call which may block."}),"\n",(0,i.jsx)(n.li,{children:"Takes a lock, and another thread takes the same lock, and before releasing it,\nmakes a call that may block."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Calls that may block are considered:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Certain I/O calls."}),"\n",(0,i.jsxs)(n.li,{children:["Two way ",(0,i.jsx)(n.code,{children:"Binder.transact"})," calls."]}),"\n",(0,i.jsx)(n.li,{children:"Certain OS calls."}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Future"})," or ",(0,i.jsx)(n.code,{children:"AsyncTask"})," calls to ",(0,i.jsx)(n.code,{children:"get"})," without timeouts, or with too large\ntimeouts."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress starvation reports in a method ",(0,i.jsx)(n.code,{children:"m()"})," use the\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STARVATION")'})," annotation, as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("STARVATION")\n public void m() {\n ...\n }\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To signal to Infer that a method does not perform any blocking calls, despite\nappearences, you can use the ",(0,i.jsx)(n.code,{children:"@NonBlocking"})," annotation:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" import com.facebook.infer.annotation.NonBlocking;\n\n @NonBlocking\n public void m() {\n ...\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This instructs Infer to filter out any potentially blocking calls in ",(0,i.jsx)(n.code,{children:"m()"}),"\n(also, transitively), and thus any other method can expect no starvation reports\ndue to a call to ",(0,i.jsx)(n.code,{children:"m()"}),". You will need to set up your class path appropriately to\ninclude the JAR files in ",(0,i.jsx)(n.code,{children:"infer/annotations"})," for this annotation to work."]}),"\n",(0,i.jsx)(n.h2,{id:"static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Static Initialization Order Fiasco" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-siof",children:"siof"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error is reported in C++. It fires when the initialization of a static\nvariable ",(0,i.jsx)(n.code,{children:"A"}),", accesses a static variable ",(0,i.jsx)(n.code,{children:"B"})," from another translation unit\n(usually another ",(0,i.jsx)(n.code,{children:".cpp"})," file). There are no guarantees whether ",(0,i.jsx)(n.code,{children:"B"})," has been\nalready initialized or not at that point."]}),"\n",(0,i.jsxs)(n.p,{children:["For more technical definition and techniques to avoid/remediate, see the\n",(0,i.jsx)(n.a,{href:"https://isocpp.org/wiki/faq/ctors#static-init-order",children:"FAQ"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strict_mode_violation",children:"STRICT_MODE_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Strict Mode Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Android has a feature called\n",(0,i.jsx)(n.a,{href:"https://developer.android.com/reference/android/os/StrictMode",children:"strict mode"}),",\nwhich if enabled, will flag the occasions where the main thread makes a call\nthat results in disk I/O, waiting on a network socket, etc. The analysis\ncatching starvation errors and deadlocks (the ",(0,i.jsx)(n.code,{children:"--starvation"})," analysis) has the\nability to statically detect such violations."]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress this warning, it's enough to annotate the offending method with\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STRICT_MODE_VIOLATION")'}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "StrongSelf Not Checked" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports a potential issue when a block captures ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),"),\nthen one assigns this pointer to a local variable ",(0,i.jsx)(n.code,{children:"strongSelf"})," inside the block and uses this variable\nwithout checking first whether it is ",(0,i.jsx)(n.code,{children:"nil"}),". The problem here is that the weak pointer could be ",(0,i.jsx)(n.code,{children:"nil"})," at\nthe time when the block is executed. So, the correct usage is to first check whether ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a valid\npointer, and then use it."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n int y = strongSelf->x;\n ...\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nAdd a check for ",(0,i.jsx)(n.code,{children:"nil"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n int y = strongSelf->x;\n ...\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"taint_error",children:"TAINT_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Taint Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A taint flow was detected from a source to a sink"}),"\n",(0,i.jsx)(n.h2,{id:"thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Thread Safety Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This warning indicates a potential data race in Java. The analyser is called\nRacerD and this section gives brief but a mostly complete description of its\nfeatures. See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"RacerD page"})," for more in-depth information and\nexamples."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-what-is-a-data-race",children:"Thread-safety: What is a data race"}),"\n",(0,i.jsx)(n.p,{children:"Here a data race is a pair of accesses to the same member field such that:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"at least one is a write, and,"}),"\n",(0,i.jsx)(n.li,{children:"at least one occurs without any lock synchronization, and,"}),"\n",(0,i.jsx)(n.li,{children:"the two accesses occur on threads (if known) which can run in parallel."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-potential-fixes",children:"Thread-safety: Potential fixes"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Synchronizing the accesses (using the ",(0,i.jsx)(n.code,{children:"synchronized"})," keyword, thread-exclusion\nsuch as atomic objects, ",(0,i.jsx)(n.code,{children:"volatile"})," etc)."]}),"\n",(0,i.jsx)(n.li,{children:"Making an offending method private -- this will exclude it from being checked\nat the top level, though it will be checked if called by a public method which\nmay itself, e.g., hold a lock when calling it."}),"\n",(0,i.jsxs)(n.li,{children:["Putting the two accesses on the same thread, e.g., by using ",(0,i.jsx)(n.code,{children:"@MainThread"})," or\n",(0,i.jsx)(n.code,{children:"@ThreadConfined"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-conditions-checked-before-reporting",children:"Thread-safety: Conditions checked before reporting"}),"\n",(0,i.jsxs)(n.p,{children:["The class and method are not marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe(enableChecks = false)"}),", and,"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method is declared ",(0,i.jsx)(n.code,{children:"synchronized"}),", or employs (non-transitively) locking,\nor,"]}),"\n",(0,i.jsxs)(n.li,{children:["The class is not marked ",(0,i.jsx)(n.code,{children:"@NotThreadSafe"}),", and,","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The class/method is marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe,"})," or one of the configured synonyms\nin ",(0,i.jsx)(n.code,{children:".inferconfig"}),", or,"]}),"\n",(0,i.jsx)(n.li,{children:"A parent class, or an override method are marked with the above annotations."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["NB currently RacerD ",(0,i.jsxs)(n.strong,{children:["does not take into account ",(0,i.jsx)(n.code,{children:"@GuardedBy"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-thread-annotations-recognized-by-racerd",children:"Thread-safety: Thread annotations recognized by RacerD"}),"\n",(0,i.jsxs)(n.p,{children:["These class and method annotations imply the method is on the main thread:\n",(0,i.jsx)(n.code,{children:"@MainThread"}),", ",(0,i.jsx)(n.code,{children:"@UiThread"})]}),"\n",(0,i.jsxs)(n.p,{children:["These method annotations imply the method is on the main thread: ",(0,i.jsx)(n.code,{children:"@OnBind"}),",\n",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnMount"}),", ",(0,i.jsx)(n.code,{children:"@OnUnbind"}),", ",(0,i.jsx)(n.code,{children:"@OnUnmount"})]}),"\n",(0,i.jsx)(n.p,{children:"Both classes of annotations work through the inheritance tree (i.e. if a parent\nclass or method is marked with one of these annotations, so is the child class /\nmethod override)."}),"\n",(0,i.jsxs)(n.p,{children:["In addition to these, RacerD recognizes many lifecycle methods as necessarily\nrunning on the main thread, eg ",(0,i.jsx)(n.code,{children:"Fragment.onCreate"})," etc."]}),"\n",(0,i.jsxs)(n.p,{children:["Finally, the thread status of being on the main thread propagates backwards\nthrough the call graph (ie if ",(0,i.jsx)(n.code,{children:"foo"})," calls ",(0,i.jsx)(n.code,{children:"bar"})," and ",(0,i.jsx)(n.code,{children:"bar"})," is marked ",(0,i.jsx)(n.code,{children:"@UiThtread"}),"\nthen ",(0,i.jsx)(n.code,{children:"foo"})," is automatically considered on the main thread too). Calling\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),", ",(0,i.jsx)(n.code,{children:"assertOnUiThread"}),", ",(0,i.jsx)(n.code,{children:"checkOnMainThread"})," has the same effect."]}),"\n",(0,i.jsxs)(n.p,{children:["NB RacerD currently ",(0,i.jsxs)(n.strong,{children:["does not recognize ",(0,i.jsx)(n.code,{children:"@WorkerThread"}),", ",(0,i.jsx)(n.code,{children:"@BinderThread"})," or\n",(0,i.jsx)(n.code,{children:"@AnyThread"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-other-annotations-and-what-they-do",children:"Thread-safety: Other annotations and what they do"}),"\n",(0,i.jsxs)(n.p,{children:["These annotations can be found at ",(0,i.jsx)(n.code,{children:"com.facebook.infer.annotation.*"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@Functional"})," This is a method annotation indicating the method always returns\nthe same value. When a method ",(0,i.jsx)(n.code,{children:"foo"})," is annotated ",(0,i.jsx)(n.code,{children:"@Functional"}),", RacerD will\nignore any writes of the return value of ",(0,i.jsx)(n.code,{children:"foo"}),". For example, in\n",(0,i.jsx)(n.code,{children:"this.x = foo()"}),", the write to ",(0,i.jsx)(n.code,{children:"this.x"})," is ignored. The reasoning is that if\nthe method returns the same value whenever it's called, any data race on\n",(0,i.jsx)(n.code,{children:"this.x"})," is benign, if that is the only write."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ThreadConfined"})," This is a class/method/field annotation which takes a single\nparameter which can be ",(0,i.jsx)(n.code,{children:"UI"}),", ",(0,i.jsx)(n.code,{children:"ANY"})," or a user chosen string. It indicates to\nRacerD a thread identifier for the class/method/field. Thus,\n",(0,i.jsx)(n.code,{children:"@ThreadConfined(UI)"})," is equivalent to ",(0,i.jsx)(n.code,{children:"@UiThread"}),", and ",(0,i.jsx)(n.code,{children:"@ThreadConfined(ANY)"}),"\nis equivalent to not having the annotation at all, for classes and methods.\nWhen this annotation is applied to a field it instructs Infer to assume\n(without checking) that all accesses to that field are made on the same thread\n(and can, therefore, not race by definition). The intention is that RacerD\nuses that to detect exclusion between accesses occurring on the same thread.\nHowever, only the UI thread is supported at this time, and any user provided\nvalue is considered equal to ",(0,i.jsx)(n.code,{children:"UI"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@VisibleForTesting"})," A method annotation making Infer consider the method as\neffectively ",(0,i.jsx)(n.code,{children:"private"}),". This means it will not be checked for races against\nother non-private methods of the class, but only if called by one."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ReturnsOwnership"})," A method annotation indicating that the method returns a\nfreshly owned object. Accesses to the returned value will not be considered\nfor data races, as the object is in-effect unique and not accessible yet from\nother threads. The main utility of this annotation is in interfaces, where\nInfer cannot look up the implementation and decide for itself."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error",children:"TOPL_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Topl Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A violation of a Topl property (user-specified).\nThere is an execution path in the code that drives a Topl property from a start state to an error state."}),"\n",(0,i.jsx)(n.p,{children:"This indicates that the code has a user-defined undesired behavior."}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/docs/next/checker-topl##what-is-it",children:"Topl"})," for an example"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error_latent",children:"TOPL_ERROR_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Topl Error Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#topl_error",children:"TOPL_ERROR"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"uninitialized_value",children:"UNINITIALIZED_VALUE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-uninit",children:"uninit"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The code uses a variable that has not been initialized, leading to unpredictable or unintended results."}),"\n",(0,i.jsx)(n.p,{children:"Using uninitialized values can lead to undefined behaviors possibly resulting in crashes, security failures and invalid results."}),"\n",(0,i.jsx)(n.p,{children:"This can easily be fixed by assigning all variables to an initial value when declaring them."}),"\n",(0,i.jsx)(n.p,{children:"This, for example, in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct coordinates {\n int x;\n int y;\n};\n\nvoid foo() {\n struct coordinates c;\n c.x = 42;\n c.y++; // uninitialized value c.y!\n\n int z;\n if (z == 0) { // uninitialized value z!\n // something\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_buffer_access",children:"UNTRUSTED_BUFFER_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Buffer Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to buffer."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_deserialization",children:"UNTRUSTED_DESERIALIZATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Deserialization" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled deserialization."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_deserialization_risk",children:"UNTRUSTED_DESERIALIZATION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Deserialization Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled deserialization"}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_environment_change_risk",children:"UNTRUSTED_ENVIRONMENT_CHANGE_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Environment Change Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled environment mutation."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_file",children:"UNTRUSTED_FILE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted File" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled file creation; may be vulnerable to path traversal and more."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_file_risk",children:"UNTRUSTED_FILE_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted File Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled file creation; may be vulnerable to path traversal and more."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_heap_allocation",children:"UNTRUSTED_HEAP_ALLOCATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Heap Allocation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to heap allocation. this can cause crashes or DOS."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_intent_creation",children:"UNTRUSTED_INTENT_CREATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Intent Creation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Creating an Intent from user-controlled data."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_url_risk",children:"UNTRUSTED_URL_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Url Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted flag, environment variable, or file data flowing to URL."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_variable_length_array",children:"UNTRUSTED_VARIABLE_LENGTH_ARRAY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Variable Length Array" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to stack buffer allocation. Trying to allocate a stack buffer that's too large will cause a stack overflow."}),"\n",(0,i.jsx)(n.h2,{id:"user_controlled_sql_risk",children:"USER_CONTROLLED_SQL_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "User Controlled Sql Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data flows to SQL (no injection risk)."}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete",children:"USE_AFTER_DELETE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Delete" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"delete"})," in C++ is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Delete Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_delete",children:"USE_AFTER_DELETE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free",children:"USE_AFTER_FREE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Free" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"free"})," in C is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free_latent",children:"USE_AFTER_FREE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Free Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_free",children:"USE_AFTER_FREE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime",children:"USE_AFTER_LIFETIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Lifetime" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The lifetime of an object has ended but that object is being\naccessed. For example, the address of a variable holding a C++ object\nis accessed after the variable has gone out of scope:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void foo() {\n X* p;\n { // new scope\n X x = X();\n p = &x;\n } // x has gone out of scope\n p->method(); // ERROR: you should not access *p after x has gone out of scope\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Lifetime Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_lifetime",children:"USE_AFTER_LIFETIME"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation",children:"VECTOR_INVALIDATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Vector Invalidation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address pointing into a C++ ",(0,i.jsx)(n.code,{children:"std::vector"})," might have become\ninvalid. This can happen when an address is taken into a vector, then\nthe vector is mutated in a way that might invalidate the address, for\nexample by adding elements to the vector, which might trigger a\nre-allocation of the entire vector contents (thereby invalidating the\npointers into the previous location of the contents)."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:'void deref_vector_element_after_push_back_bad(std::vector& vec) {\n int* elt = &vec[1];\n vec.push_back(42); // if the array backing the vector was full already, this\n // will re-allocate it and copy the previous contents\n // into the new array, then delete the previous array\n std::cout << *y << "\\n"; // bad: elt might be invalid\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Vector Invalidation Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#vector_invalidation",children:"VECTOR_INVALIDATION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"weak_self_in_no_escape_block",children:"WEAK_SELF_IN_NO_ESCAPE_BLOCK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Weak Self In No Escape 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 reports when ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),') is used in\na block, and this block is passed to a "no escaping" method. This means that\nthe block passed to that method won\'t be leaving the current scope, this is\nmarked with the annotation ',(0,i.jsx)(n.code,{children:"NS_NOESCAPE"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:['The issue here is that, because the block is "no escaping", there is no need to use\n',(0,i.jsx)(n.code,{children:"weakSelf"})," and ",(0,i.jsx)(n.code,{children:"strongSelf"})," but we can just use ",(0,i.jsx)(n.code,{children:"self"}),". This has the advantage of\nnot needing to deal with the added complexity of weak pointers, and it simplifies the\ncode."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n [self foo:^() { //foo's first parameter is annotates with `NS_NOESCAPE`\n [weakSelf bar];\n }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Replace ",(0,i.jsx)(n.code,{children:"weakSelf"})," with ",(0,i.jsx)(n.code,{children:"self"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" [self foo:^() {\n [self bar];\n }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,r.M)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2172:(e,n,s)=>{s.d(n,{I:()=>l,M:()=>a});var i=s(1504);const r={},t=i.createContext(r);function a(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c359af60.c62dc728.js b/assets/js/c359af60.c62dc728.js new file mode 100644 index 00000000000..78f2af9ac17 --- /dev/null +++ b/assets/js/c359af60.c62dc728.js @@ -0,0 +1 @@ +"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_DICT_MISSING_KEY",id:"pulse_dict_missing_key",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:"#include \nint foo(){\n const std::vector vec;\n return vec[0]; // Empty vector access reported here\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase",children:"EXECUTION_TIME_COMPLEXITY_INCREASE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Complexity Increase" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of a\nprogram increases in degree: e.g. from constant to linear or from\nlogarithmic to quadratic. This issue type is only reported in\ndifferential mode: i.e when we are comparing the cost analysis results of\ntwo runs of infer on a file. Check out examples in ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost#examples",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_complexity_increase_ui_thread",children:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Complexity Increase Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of the procedure increases in degree ",(0,i.jsx)(n.strong,{children:"and"})," the procedure runs on the UI (main) thread."]}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"execution_time_unreachable_at_exit",children:"EXECUTION_TIME_UNREACHABLE_AT_EXIT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Execution Time Unreachable At Exit" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates that the program's execution doesn't reach\nthe exit node (where our analysis computes the final cost of the\nprocedure). Hence, we cannot compute a static bound for the procedure."}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void exit_unreachable() {\n exit(0); // modeled as unreachable\n}\n\nvoid infeasible_path_unreachable() {\n Preconditions.checkState(false); // like assert false, state pruned to bottom\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_execution_time",children:"EXPENSIVE_EXECUTION_TIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Expensive Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["[EXPERIMENTAL] This warning indicates that the procedure has non-constant and non-top execution cost. By default, this issue type is disabled. To enable it, set ",(0,i.jsx)(n.code,{children:"enabled=true"})," in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/base/costKind.ml#L55",children:"costKind.ml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"For instance, a simple example where we report this issue is a function with linear cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int sum_linear(ArrayList list){\n int sum = 0;\n for (Integer el: list){\n sum += el;\n }\n return sum;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"expensive_loop_invariant_call",children:"EXPENSIVE_LOOP_INVARIANT_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Expensive Loop Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["We report this issue type when a function is ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#invariant_call",children:"loop-invariant"})," and also expensive (i.e. at least has linear complexity as determined by the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"})," analysis)."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int incr(int x) {\n return x + 1;\n}\n\n// incr will not be hoisted since it is cheap(constant time)\nvoid foo_linear(int size) {\n int x = 10;\n for (int i = 0; i < size; i++) {\n incr(x); // constant call, don't hoist\n }\n}\n\n// call to foo_linear will be hoisted since it is expensive(linear in size).\nvoid symbolic_expensive_hoist(int size) {\n for (int i = 0; i < size; i++) {\n foo_linear(size); // hoist\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"exposed_insecure_intent_handling",children:"EXPOSED_INSECURE_INTENT_HANDLING"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Exposed Insecure Intent Handling" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"guardedby_violation",children:"GUARDEDBY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "GuardedBy Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A field annotated with ",(0,i.jsx)(n.code,{children:"@GuardedBy"})," is being accessed by a call-chain that starts at a non-private method without synchronization."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'class C {\n @GuardedBy("this")\n String f;\n\n void foo(String s) {\n f = s; // unprotected access here\n }\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Action: Protect the offending access by acquiring the lock indicated by the ",(0,i.jsx)(n.code,{children:"@GuardedBy(...)"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"impure_function",children:"IMPURE_FUNCTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Impure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates impure functions. For instance, below functions would be marked as impure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void makeAllZero_impure(ArrayList list) {\n Iterator listIterator = list.iterator();\n while (listIterator.hasNext()) {\n Foo foo = listIterator.next();\n foo.x = 0;\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Inefficient Keyset Iterator" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"inefficient-keyset-iterator"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue is raised when"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["iterating over a HashMap with ",(0,i.jsx)(n.code,{children:"ketSet()"})," iterator"]}),"\n",(0,i.jsx)(n.li,{children:"looking up the key each time"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void inefficient_loop_bad(HashMap testMap) {\n for (String key : testMap.keySet()) {\n Integer value = testMap.get(key); // extra look-up cost\n foo(key, value);\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Instead, it is more efficient to iterate over the loop with ",(0,i.jsx)(n.code,{children:"entrySet"})," which returns key-vaue pairs and gets rid of the hashMap lookup."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void efficient_loop_ok(HashMap testMap) {\n for (Map.Entry entry : testMap.entrySet()) {\n String key = entry.getKey();\n Integer value = entry.getValue();\n foo(key, value);\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_big",children:"INFERBO_ALLOC_IS_BIG"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is passed a large constant value (>=10^6). For example, ",(0,i.jsx)(n.code,{children:"int n = 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument or make sure it is really needed."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_negative",children:"INFERBO_ALLOC_IS_NEGATIVE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a negative size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_is_zero",children:"INFERBO_ALLOC_IS_ZERO"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc Is Zero" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," is called with a zero size. For example, ",(0,i.jsx)(n.code,{children:"int n = 3 - 3; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_IS_ZERO"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_big",children:"INFERBO_ALLOC_MAY_BE_BIG"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc May Be Big" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a large value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : 1000000; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_BIG"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n < A_SMALL_NUMBER) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"inferbo_alloc_may_be_negative",children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Alloc May Be Negative" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"malloc"})," ",(0,i.jsx)(n.em,{children:"may"})," be called with a negative value. For example, ",(0,i.jsx)(n.code,{children:"int n = b ? 3 : -5; malloc(n);"})," generates ",(0,i.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"})," on ",(0,i.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,i.jsx)(n.code,{children:"if (n > 0) { malloc(n); }"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"infinite_execution_time",children:"INFINITE_EXECUTION_TIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Infinite Execution Time" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This warning indicates that Infer was not able to determine a static\nupper bound on the execution cost of the procedure. By default, this\nissue type is disabled."}),"\n",(0,i.jsx)(n.h3,{id:"example-1-t-due-to-expressivity",children:"Example 1: T due to expressivity"}),"\n",(0,i.jsx)(n.p,{children:"For instance, Inferbo's interval analysis is limited to affine\nexpressions. Hence, we can't statically estimate an upper bound on the\nbelow example and obtain T(unknown) cost:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: square root(x), got T\nvoid square_root_FP(int x) {\n int i = 0;\n while (i * i < x) {\n i++;\n }\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"example-2-t-due-to-unmodeled-calls",children:"Example 2: T due to unmodeled calls"}),"\n",(0,i.jsx)(n.p,{children:"Another common case where we get T cost is when Infer cannot statically determine the range of values for loop bounds. For instance,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void loop_over_charArray_FP(StringBuilder builder, String input) {\n for (Character c : input.toCharArray()) {}\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Here, Infer does not have any InferBo models for the range of values returned by ",(0,i.jsx)(n.code,{children:"String.toCharArray"}),", hence it cannot determine that we will be iterating over a char array in the size of ",(0,i.jsx)(n.code,{children:"input"})," string."]}),"\n",(0,i.jsxs)(n.p,{children:["To teach InferBo about such library calls, they should be semantically modeled in ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/bufferoverrun/bufferOverrunModels.ml",children:"InferBo"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"example-3-t-due-to-calling-another-t-costed-function",children:"Example 3: T due to calling another T-costed function"}),"\n",(0,i.jsx)(n.p,{children:"Since the analysis is inter-procedural, another example we can have T cost is if at least one of the callees has T cost."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// Expected: constant, got T\nvoid call_top_cost_FP() {\n square_root_FP(1); // square_root_FP has Top cost\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"insecure_intent_handling",children:"INSECURE_INTENT_HANDLING"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Insecure Intent Handling" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L1" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when integer overflow occurred by integer operations such as addition, subtraction,\nand multiplication. For example, ",(0,i.jsx)(n.code,{children:"int n = INT_MAX; int m = n + 3;"})," generates a INTEGER_OVERFLOW_L1\non ",(0,i.jsx)(n.code,{children:"n + 3"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'Integer overflows reports fall into several "buckets" corresponding to the expected precision of the\nreport. The higher the number, the more likely it is to be a false positive.'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,i.jsx)(n.em,{children:"must"})," be unsafe. For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [1,1]"})," in 32-bit signed integer type."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,i.jsx)(n.code,{children:"L1"}),", when it ",(0,i.jsx)(n.em,{children:"may"})," be unsafe. For example,\n",(0,i.jsx)(n.code,{children:"[2147483647,2147483647] + [0,1]"})," in 32-bit signed integer type. Note that the integer of RHS\ncan be 0, which is safe."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"L5"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"U5"}),": A binary integer operation is unsafe by unknown values, which are usually from unknown\nfunction calls."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l2",children:"INTEGER_OVERFLOW_L2"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L2" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_l5",children:"INTEGER_OVERFLOW_L5"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow L5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"integer_overflow_u5",children:"INTEGER_OVERFLOW_U5"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Integer Overflow U5" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,i.jsx)(n.h2,{id:"interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Interface Not Thread Safe" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error indicates that you have invoked an interface method not annotated\nwith ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," from a thread-safe context (e.g., code that uses locks or is\nmarked ",(0,i.jsx)(n.code,{children:"@ThreadSafe"}),"). The fix is to add the ",(0,i.jsx)(n.code,{children:"@ThreadSafe"})," annotation to the\ninterface or to the interface method. For background on why these annotations\nare needed, see the detailed explanation\n",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd#interface-not-thread-safe",children:"here"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"invalid_sil",children:"INVALID_SIL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Invalid Sil" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-sil-validation",children:"sil-validation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The SIL instruction does not conform to the expected subset of instructions\nexpected for the front-end of the language for the analyzed code."}),"\n",(0,i.jsx)(n.h2,{id:"invariant_call",children:"INVARIANT_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Invariant Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"We report this issue type when a function call is loop-invariant and hoistable, i.e."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the function has no side side effects (pure)"}),"\n",(0,i.jsx)(n.li,{children:"has invariant arguments and result (i.e. have the same value in all loop iterations)"}),"\n",(0,i.jsx)(n.li,{children:"it is guaranteed to execute, i.e. it dominates all loop sources"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int foo(int x, int y) {\n return x + y;\n}\n\n\nvoid invariant_hoist(int size) {\n int x = 10;\n int y = 5;\n for (int i = 0; i < size; i++) {\n foo(x, y); // hoistable\n }\n }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Ipc On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A blocking ",(0,i.jsx)(n.code,{children:"Binder"})," IPC call occurs on the UI thread."]}),"\n",(0,i.jsx)(n.h2,{id:"javascript_injection",children:"JAVASCRIPT_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Javascript Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data flows into JavaScript."}),"\n",(0,i.jsx)(n.h2,{id:"lab_resource_leak",children:"LAB_RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lab Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-resource-leak-lab",children:"resource-leak-lab"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Toy issue."}),"\n",(0,i.jsx)(n.h2,{id:"lockless_violation",children:"LOCKLESS_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lockless Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A method implements an interface signature annotated with ",(0,i.jsx)(n.code,{children:"@Lockless"})," but which transitively acquires a lock."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"Interface I {\n @Lockless\n public void no_lock();\n}\n\nclass C implements I {\n private synchronized do_lock() {}\n\n public void no_lock() { // this method should not acquire any locks\n do_lock();\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Lock Consistency Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is an error reported on C++ and Objective C classes whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Some class method directly uses locking primitives (not transitively)."}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which writes to some member ",(0,i.jsx)(n.code,{children:"x"})," while holding a lock."]}),"\n",(0,i.jsxs)(n.li,{children:["It has a public method which reads ",(0,i.jsx)(n.code,{children:"x"})," without holding a lock."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The above may happen through a chain of calls. Above, ",(0,i.jsx)(n.code,{children:"x"})," may also be a\ncontainer (an array, a vector, etc)."]}),"\n",(0,i.jsx)(n.h3,{id:"fixing-lock-consistency-violation-reports",children:"Fixing Lock Consistency Violation reports"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Avoid the offending access (most often the read). Of course, this may not be\npossible."}),"\n",(0,i.jsx)(n.li,{children:"Use synchronization to protect the read, by using the same lock protecting the\ncorresponding write."}),"\n",(0,i.jsx)(n.li,{children:"Make the method doing the read access private. This should silence the\nwarning, since Infer looks for a pair of non-private methods. Objective-C:\nInfer considers a method as private if it's not exported in the header-file\ninterface."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"logging_private_data",children:"LOGGING_PRIVATE_DATA"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Logging Private Data" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Undocumented."}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_c",children:"MEMORY_LEAK_C"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-c",children:"Memory leak in C"}),"\n",(0,i.jsx)(n.p,{children:"This error type is only reported in C and Objective-C code. In Java we do not\nreport memory leaks because it is a garbage collected language."}),"\n",(0,i.jsxs)(n.p,{children:["In C, Infer reports memory leaks when objects are created with ",(0,i.jsx)(n.code,{children:"malloc"})," and not\nfreed. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"-(void) memory_leak_bug {\n struct Person *p = malloc(sizeof(struct Person));\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"memory-leak-in-objective-c",children:"Memory leak in Objective-C"}),"\n",(0,i.jsx)(n.p,{children:"Additionally, in Objective-C, Infer reports memory leaks that happen when\nobjects from Core Foundation or Core Graphics don't get released."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) memory_leak_bug_cf {\n CGPathRef shadowPath = CGPathCreateWithRect(self.inputView.bounds, NULL); //object created and not released.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"memory_leak_cpp",children:"MEMORY_LEAK_CPP"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Memory Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"})]}),"\n",(0,i.jsx)(n.h2,{id:"missing_required_prop",children:"MISSING_REQUIRED_PROP"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Missing Required Prop" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-litho-required-props",children:"litho-required-props"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issues is reported when a required ",(0,i.jsx)(n.code,{children:"@Prop"})," is missing."]}),"\n",(0,i.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,i.jsxs)(n.p,{children:["Assume that the following Litho Component specification is defined as follows where ",(0,i.jsx)(n.code,{children:"prop1"})," is optional and ",(0,i.jsx)(n.code,{children:"prop2"})," is required."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n static void onCreate(\n ComponentContext c,\n @Prop(optional = true) String prop1, @Prop int prop2) {\n ...\n }\n ...\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["When we build the corresponding component, we should have all the required props. If we are missing optional props (e..g ",(0,i.jsx)(n.code,{children:"prop1"})," below), it is ok."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"MyComponent.create(c)\n .prop2(8)\n .build();\n"})}),"\n",(0,i.jsxs)(n.p,{children:["However, if we are missing a required prop, Infer gives an error below for the missing ",(0,i.jsx)(n.code,{children:"prop2"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .build();\n'})}),"\n",(0,i.jsx)(n.p,{children:"** Action **"}),"\n",(0,i.jsx)(n.p,{children:"There are two ways to fix this issue."}),"\n",(0,i.jsxs)(n.p,{children:["First, we could add the missing ",(0,i.jsx)(n.code,{children:"prop2"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .prop2(x) // where x is some integer\n .build();\n'})}),"\n",(0,i.jsxs)(n.p,{children:["or alternatively, if the ",(0,i.jsx)(n.code,{children:"prop2"})," is not really required, we could change the component spec to reflect that:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"class MyComponentSpec {\n\n static void onCreate(\n ComponentContext c,\n @Prop(optional = true) String prop1, @Prop(optional = true) int prop2) {\n ...\n }\n ...\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Mixed Self WeakSelf" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports an issue when an Objective-C block captures both ",(0,i.jsx)(n.code,{children:"self"})," and ",(0,i.jsx)(n.code,{children:"weakSelf"}),", a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),".\nPossibly the developer meant to capture only ",(0,i.jsx)(n.code,{children:"weakSelf"})," to avoid a retain cycle, but made a typo and used ",(0,i.jsx)(n.code,{children:"self"}),"\ninstead of ",(0,i.jsx)(n.code,{children:"strongSelf"}),". In this case, this could cause a retain cycle."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n int x = self->x; // typo here\n }\n return 0;\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),": Fixing the typo is generally the right course of action."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"modifies_immutable",children:"MODIFIES_IMMUTABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Modifies Immutable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue type indicates modifications to fields marked as @Immutable. For instance, below function ",(0,i.jsx)(n.code,{children:"mutateArray"})," would be marked as modifying immutable field ",(0,i.jsx)(n.code,{children:"testArray"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" @Immutable int[] testArray = new int[]{0, 1, 2, 4};\n \n int[] getTestArray() {\n return testArray;\n } \n \n void mutateArray() {\n int[] array = getTestArray();\n array[2] = 7;\n }\n"})}),"\n",(0,i.jsx)(n.h2,{id:"multiple_weakself",children:"MULTIPLE_WEAKSELF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Multiple WeakSelf Use" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when an Objective-C block uses ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),") more than once.\nThis could lead to unexpected behaviour. Even if ",(0,i.jsx)(n.code,{children:"weakSelf"})," is not nil in the first use, it could be nil\nin the following uses since the object that ",(0,i.jsx)(n.code,{children:"weakSelf"})," points to could be freed anytime."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n [weakSelf foo];\n int x = weakSelf->x;\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nOne should assign ",(0,i.jsx)(n.code,{children:"weakSelf"})," to a strong pointer first, and then\nuse it in the block."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n int x = strongSelf->x;\n }\n ...\n };\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call",children:"NIL_BLOCK_CALL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Block Call" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This check reports when one tries to call an Objective-C block that is ",(0,i.jsx)(n.code,{children:"nil"}),".\nThis causes a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"-(void) foo:(void (^)())callback {\n callback();\n}\n\n-(void) bar {\n [self foo:nil]; //crash\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling the block, or making sure never to call the method ",(0,i.jsx)(n.code,{children:"foo:"})," with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Block Call Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_block_call",children:"NIL_BLOCK_CALL"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports when ",(0,i.jsx)(n.code,{children:"nil"})," is passed to collections in Objective-C such as arrays and dictionaries. This causes a crash."]}),"\n",(0,i.jsx)(n.h3,{id:"arrays",children:"Arrays"}),"\n",(0,i.jsxs)(n.p,{children:["Adding objects to an array, inserting objects at a given index, or replacing objects at a given index, can all\nlead to a crash when the object is ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" [mArray addObject:nil]; //crash\n\n [mArray insertObject:nil atIndex:0]; //crash\n\n [mArray replaceObjectAtIndex:0 withObject:nil]; //crash\n"})}),"\n",(0,i.jsx)(n.h3,{id:"dictionaries",children:"Dictionaries"}),"\n",(0,i.jsxs)(n.p,{children:["Adding a ",(0,i.jsx)(n.code,{children:"nil"})," value in a dictionary causes a crash. If the concept of ",(0,i.jsx)(n.code,{children:"nil"})," is required, one can add\n",(0,i.jsx)(n.code,{children:"[NSNull null]"})," instead."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' id value = nil;\n [mDict setObject:value forKey:@"somestring"]; //crash\n\n [mDict setObject:[NSNull null] forKey:@"somestring"]; //ok\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Retrieving or removing an object from a dictionary with a ",(0,i.jsx)(n.code,{children:"nil"})," key also causes a crash:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' id key = nil;\n mDict[key] = @"somestring"; //crash\n\n [mDict removeObjectForKey:nil]; //crash\n'})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["In all the cases above, when passing ",(0,i.jsx)(n.code,{children:"nil"})," causes a crash, the solutions are either making sure\nthat the object passed will never be ",(0,i.jsx)(n.code,{children:"nil"}),", or adding a check for ",(0,i.jsx)(n.code,{children:"nil"})," before calling those methods."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Insertion Into Collection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Messaging To Non Pod" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, calling a method on ",(0,i.jsx)(n.code,{children:"nil"})," (or in Objective-C terms, sending a message to ",(0,i.jsx)(n.code,{children:"nil"}),") does not crash,\nit simply returns a falsy value (nil/0/false). However, sending a message that returns\na non-POD C++ type (POD being ",(0,i.jsx)(n.a,{href:"https://en.cppreference.com/w/cpp/named_req/PODType",children:'"Plain Old Data"'}),", essentially\nanything that cannot be compiled as a C-style struct) to ",(0,i.jsx)(n.code,{children:"nil"})," causes undefined behaviour."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr callMethodReturnsnonPOD() {\n SomeObject* obj = getObjectOrNil();\n std::shared_ptr d = [obj returnsnonPOD]; // UB\n return d;\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["To fix the above issue, we need to check if ",(0,i.jsx)(n.code,{children:"obj"})," is\nnot ",(0,i.jsx)(n.code,{children:"nil"})," before calling the ",(0,i.jsx)(n.code,{children:"returnsnonPOD"})," method:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"std::shared_ptr callMethodReturnsnonPOD(bool b) {\n SomeObject* obj = getObjectOrNil(b);\n if (obj == nil) { return std::make_shared(0); }\n std::shared_ptr d = [obj returnsnonPOD];\n return d;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Nil Messaging To Non Pod Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Branch In Try" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching branch is found when evaluating the ",(0,i.jsx)(n.code,{children:"of"})," section of a ",(0,i.jsx)(n.code,{children:"try"})," expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{try_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n try X of\n [_|T] -> {ok,T}\n catch\n _ -> error\n end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Branch In Try Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Case Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching case clause in Erlang: Reports an error when none of the clauses of a ",(0,i.jsx)(n.code,{children:"case"})," match the expression. Corresponds to the ",(0,i.jsx)(n.code,{children:"{case_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n case X of\n [_|T] -> T\n end.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Case Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Function Clause" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No matching function clause in Erlang: Reports an error when none of the clauses of a function match the arguments of a call. Corresponds to the ",(0,i.jsx)(n.code,{children:"function_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,i.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"tail([_|Xs]) -> Xs.\n"})}),"\n",(0,i.jsx)(n.p,{children:"This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses."}),"\n",(0,i.jsx)(n.h2,{id:"no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Matching Function Clause Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Match Of Rhs" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No match of right hand side value in Erlang: Reports an error when the right hand side value of a ",(0,i.jsx)(n.code,{children:"match"})," expression does not match the pattern on the left hand side. Corresponds to the ",(0,i.jsx)(n.code,{children:"{badmatch,V}"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, ",(0,i.jsx)(n.code,{children:"[H|T] = []"})," gives the error because the left hand side pattern requires at least one element in the list on the right hand side."]}),"\n",(0,i.jsx)(n.h2,{id:"no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No Match Of Rhs Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No True Branch In If" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["No true branch when evaluating an if expression in Erlang: Reports an error when none of the branches of an ",(0,i.jsx)(n.code,{children:"if"})," expression evaluate to true. Corresponds to the ",(0,i.jsx)(n.code,{children:"if_clause"})," error in the Erlang runtime."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, if we call ",(0,i.jsx)(n.code,{children:"sign(0)"})," and the full definition of ",(0,i.jsx)(n.code,{children:"sign"})," is"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-erlang",children:"sign(X) ->\n if\n X > 0 -> positive;\n X < 0 -> negative\n end.\n"})}),"\n",(0,i.jsx)(n.h2,{id:"no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "No True Branch In If Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" p = foo(); // foo() might return null\n stuff();\n p.goo(); // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n //... intervening code\n\n p = checkNotNull(foo()); // foo() might return null\n stuff();\n p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n int age;\n int height;\n int weight;\n};\nint get_age(struct Person *who) {\n return who->age;\n}\nint null_pointer_interproc() {\n struct Person *joe = 0;\n return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param { // passing nil\n D* d = [param bar]; // nil message passing\n return d->fld; // crash\n}\n(void) callFoo {\n C* c = [self bar]; // returns nil\n [foo:c]; // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports null dereference bugs in Java, C, C++, and Objective-C\nwhen it is possible that the null pointer is dereferenced, leading to\na crash."}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-java-1",children:"Null dereference in Java"}),"\n",(0,i.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" p = foo(); // foo() might return null\n stuff();\n p.goo(); // dereferencing p, potential NPE\n"})}),"\n",(0,i.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,i.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Change the code to ensure that ",(0,i.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Add a check that ",(0,i.jsx)(n.code,{children:"p"})," is not ",(0,i.jsx)(n.code,{children:"null"})," before dereferencing ",(0,i.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,i.jsx)(n.code,{children:"p"}),"\nis ",(0,i.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,i.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"// code idiom for failing early\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n //... intervening code\n\n p = checkNotNull(foo()); // foo() might return null\n stuff();\n p.goo(); // p cannot be null here\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The call ",(0,i.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,i.jsx)(n.code,{children:"null"}),": if ",(0,i.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,i.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,i.jsxs)(n.p,{children:["Facebook NOTE: ",(0,i.jsx)(n.strong,{children:"If you are absolutely sure that foo() will not be\nnull"}),", then if you land your diff this case will no longer be\nreported after your diff makes it to trunk."]}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-c-1",children:"Null dereference in C"}),"\n",(0,i.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct Person {\n int age;\n int height;\n int weight;\n};\nint get_age(struct Person *who) {\n return who->age;\n}\nint null_pointer_interproc() {\n struct Person *joe = 0;\n return get_age(joe);\n}\n"})}),"\n",(0,i.jsx)(n.h3,{id:"null-dereference-in-objective-c-1",children:"Null dereference in Objective-C"}),"\n",(0,i.jsxs)(n.p,{children:["In Objective-C, null dereferences are less common than in Java, but they still\nhappen and their cause can be hidden. In general, passing a message to nil does\nnot cause a crash and returns ",(0,i.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"(int) foo:(C*) param { // passing nil\n D* d = [param bar]; // nil message passing\n return d->fld; // crash\n}\n(void) callFoo {\n C* c = [self bar]; // returns nil\n [foo:c]; // crash reported here\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,i.jsx)(n.code,{children:"nil"})," check either for ",(0,i.jsx)(n.code,{children:"param"})," above or for ",(0,i.jsx)(n.code,{children:"d"}),", or making sure that ",(0,i.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,i.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Calling a ",(0,i.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Moreover, inserting ",(0,i.jsx)(n.code,{children:"nil"})," into a collection will cause a crash as well. We\nalso have a dedicated issue type for this case:\n",(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"null_argument",children:"NULL_ARGUMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Argument" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objc",children:"This issue type indicates `nil` being passed as argument where a non-nil value expected.\n\n#import \n\n// Test (non-nil) returned values of NSString methods against `nil`\nNSString* stringNotNil(NSString* str) {\n if (!str) {\n // ERROR: NSString:stringWithString: expects a non-nil value\n\treturn [NSString stringWithString:nil];\n }\n return str;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"null_argument_latent",children:"NULL_ARGUMENT_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Argument Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#null_argument",children:"NULL_ARGUMENT"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"null_dereference",children:"NULL_DEREFERENCE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Null Dereference" 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:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Optional Empty Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Optional Empty Access warnings are reported when we try to retrieve the value of a ",(0,i.jsx)(n.a,{href:"https://github.com/facebook/folly/blob/master/folly/Optional.h",children:(0,i.jsx)(n.code,{children:"folly::Optional"})})," when it is empty (i.e. ",(0,i.jsx)(n.code,{children:"folly::none"}),")."]}),"\n",(0,i.jsxs)(n.p,{children:["In the following example we get a warning as ",(0,i.jsx)(n.code,{children:"int_opt"})," might be ",(0,i.jsx)(n.code,{children:"folly::none"})," and its value is being accessed:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v);\n\nfolly::Optional mightReturnNone(int v) {\n if (somef(v)) {\n return folly::Optional(v);\n }\n\n return folly::none;\n}\n\nint value_no_check() {\n folly::Optional int_opt = mightReturnNone (4);\n return int_opt.value(); // Optional Empty Access warning\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["We do not get the warning anymore if we add a check whether ",(0,i.jsx)(n.code,{children:"int_opt"})," is not empty:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"int value_check() {\n folly::Optional int_opt = mightReturnNone (4);\n if (int_opt.has_value()) {\n return int_opt.value(); // OK\n }\n return -1;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"In some cases we know that we have a non-empty value and there is no need to have a check. Consider the following example where Infer does not warn:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"bool somef(int v) {return v > 3;};\n\nfolly::Optional mightReturnNone(int v) {\n if (somef(v)) {\n return folly::Optional(v);\n }\n\n return folly::none;\n}\n\nint value_no_check() {\n folly::Optional int_opt = mightReturnNone (4); // cannot be folly::none\n return int_opt.value(); // OK\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Optional Empty Access Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"premature_nil_termination_argument",children:"PREMATURE_NIL_TERMINATION_ARGUMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Premature Nil Termination Argument" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error type is reported in C and Objective-C. In many variadic methods,\n",(0,i.jsx)(n.code,{children:"nil"})," is used to signify the end of the list of input objects. This is similar\nto nil-termination of C strings. If one of the arguments that is not the last\nargument to the method is ",(0,i.jsx)(n.code,{children:"nil"})," as well, Infer reports an error because that may\nlead to unexpected behavior."]}),"\n",(0,i.jsxs)(n.p,{children:["An example of such variadic methods is\n",(0,i.jsx)(n.a,{href:"https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/index.html#//apple_ref/occ/clm/NSArray/arrayWithObjects",children:"arrayWithObjects"})]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:' NSArray *foo = [NSArray arrayWithObjects: @"aaa", str, @"bbb", nil];\n'})}),"\n",(0,i.jsxs)(n.p,{children:["In this example, if ",(0,i.jsx)(n.code,{children:"str"})," is ",(0,i.jsx)(n.code,{children:"nil"})," then an array ",(0,i.jsx)(n.code,{children:'@[@"aaa"]'})," of size 1 will be\ncreated, and not an array ",(0,i.jsx)(n.code,{children:'@[@"aaa", str, @"bbb"]'})," of size 3 as expected."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_const_refable",children:"PULSE_CONST_REFABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Const Refable Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a function parameter is a) passed by value and b) is not modified inside the function. Instead, parameter can be passed by const reference, i.e. converted to a ",(0,i.jsx)(n.code,{children:"const&"})," so that no unnecessary copy is created at the callsite of the function."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include \n\nint read_first(const std::vector& vec) { return vec[0]; }\n\nvoid const_refable(std::vector vec) {\n int first = read_first(vec); // vec is never modified, so the parameter should have type const&\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Dict Missing Key" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsxs)(n.a,{href:"#uninitialized_value",children:[(0,i.jsx)(n.code,{children:"UNINITIALIZED_VALUE"})," issue"]}),", but it is to warn\nreading a missing key of dictionary in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the dictionary ",(0,i.jsx)(n.code,{children:"$d"})," has no entry for ",(0,i.jsx)(n.code,{children:"bye"}),", so reading\n",(0,i.jsx)(n.code,{children:"$d['bye']"})," will throw the ",(0,i.jsx)(n.code,{children:"OutOfBoundsException"})," exception, which is usually unexpected from\ndevelopers. We can use a safer function ",(0,i.jsx)(n.code,{children:"idx"})," instead when keys of a dictionary is unclear."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"function simple_bad() : int {\n $d = dict['hi' => 42, 'hello' => 52];\n return $d['bye'];\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Read-only Shared Parameter" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is reported when a shared pointer parameter is a) passed by value and b) is used only for reading, rather than lifetime extension. At the callsite, this might cause a potentially expensive unnecessary copy of the shared pointer, especially when many number of threads are sharing it. To avoid this, consider 1) passing the raw pointer instead and 2) use ",(0,i.jsx)(n.code,{children:"std::shared_ptr::get"})," at callsites."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(std::shared_ptr x) {\n // read_T(*x);\n}\n\nvoid caller() {\n callee(shared_ptr);\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"can be changed to"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(T* p) {\n // read_T(*p);\n}\n\nvoid caller() {\n callee(shared_ptr.get());\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Reference Stability" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["The family of maps ",(0,i.jsx)(n.code,{children:"folly::F14ValueMap"}),", ",(0,i.jsx)(n.code,{children:"folly::F14VectorMap"}),", and by extension\n",(0,i.jsx)(n.code,{children:"folly::F14FastMap"})," differs slightly from ",(0,i.jsx)(n.code,{children:"std::unordered_map"})," as it does not\nprovide reference stability. When the map resizes such as when ",(0,i.jsx)(n.code,{children:"reserve"})," is\ncalled or new elements are added, all existing references become invalid and\nshould not be used."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"operator[]"})," is an interesting case as it can easily introduce unsafe code when\nused twice in the same expression. Depending on what keys are present and which\norder the compiler sequences sub-expressions, an insert via ",(0,i.jsx)(n.code,{children:"operator[]"})," can\ninvalidate a reference obtained in the same expression before it's read from.\nTypically, those cases can be improved by using other map functions such as\n",(0,i.jsx)(n.code,{children:"at"}),", ",(0,i.jsx)(n.code,{children:"find"}),", ",(0,i.jsx)(n.code,{children:"emplace"}),", or ",(0,i.jsx)(n.code,{children:"insert_or_assign"})," to increase code quality and\nsafety."]}),"\n",(0,i.jsx)(n.p,{children:"Examples:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"#include \n\nvoid use_reference_after_growth_bad(folly::F14FastMap& map) {\n const auto& valueRef = map.at(1);\n map.emplace(13, 71);\n const auto valueCopy = valueRef;\n}\n\nvoid unsafe_expressions_bad(folly::F14FastMap& map) {\n // Unsafe expressions in situations where one or both keys are not present.\n map[13] = map[71];\n const auto p = map[13] * map[71];\n const auto q = f(map[13], map[71]);\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#resource_leak",children:"RESOURCE_LEAK"})]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Transitive Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue tracks spurious accesses that are reachable from specific entry functions."}),"\n",(0,i.jsx)(n.p,{children:"Spurious accesses are specified as specific load/calls."}),"\n",(0,i.jsx)(n.p,{children:"Entry functions are specified through their enclosing class that must extend a specific\nclass and should not extend a list of specific classes."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unawaited Awaitable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"Awaitable"})," values created by calls to asynchronous methods should eventually be ",(0,i.jsx)(n.code,{children:"await"}),"ed along all codepaths (even if their value is unused). Hence the following is ",(0,i.jsx)(n.em,{children:"not"})," OK"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:"class A {\n public static async genInt() : Awaitable{\n // typically do something involving IO\n }\n\n public static async genBad() : Awaitable {\n $_unused = self::genInt(); // ERROR: should have done $_unused = await self::genInt();\n return;\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Failure to ",(0,i.jsx)(n.code,{children:"await"})," an ",(0,i.jsx)(n.code,{children:"Awaitable"})," can lead to non-deterministic amount of the asynchronous call actually being executed, and can also indicate a logical confusion between ",(0,i.jsx)(n.code,{children:"T"})," and ",(0,i.jsx)(n.code,{children:"Awaitable"})," that may not be caught by the type-checker."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This issue is similar to ",(0,i.jsxs)(n.a,{href:"#uninitialized_value",children:[(0,i.jsx)(n.code,{children:"UNINITIALIZED_VALUE"})," issue"]}),", but it is to detect the uninitialized abstract const value in Hack."]}),"\n",(0,i.jsxs)(n.p,{children:["For example, in the following code, the ",(0,i.jsx)(n.code,{children:"FIELD"})," can be read by the static method ",(0,i.jsx)(n.code,{children:"get_field"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["It is problematic invoking ",(0,i.jsx)(n.code,{children:"static::FIELD"}),", since it may be resolved to a ",(0,i.jsx)(n.code,{children:"A::FIELD"})," access, if called from ",(0,i.jsx)(n.code,{children:"A::get_field()"}),". Because ",(0,i.jsx)(n.code,{children:"FIELD"})," is abstract in ",(0,i.jsx)(n.code,{children:"A"}),", it is never assigned a value and the vm will crash. Unfortunately, Hack's type system cannot catch this."]}),"\n",(0,i.jsxs)(n.li,{children:["In the ",(0,i.jsx)(n.code,{children:"B"})," class, ",(0,i.jsx)(n.code,{children:"FIELD"})," is initialized, thus invoking ",(0,i.jsx)(n.code,{children:"B::get_field"})," is safe."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-hack",children:'abstract class A {\n abstract const string FIELD;\n \n public static function get_field(): string {\n return static::FIELD;\n }\n}\n\nfunction call_get_field_bad(): string {\n return A::get_field();\n}\n\nclass B extends A {\n const string FIELD = "defined";\n}\n\nfunction call_get_field_ok(): string {\n return B::get_field();\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#uninitialized_value",children:"UNINITIALIZED_VALUE"}),". Re-implemented using Pulse."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_uninitialized_value_latent",children:"PULSE_UNINITIALIZED_VALUE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" 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:"#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy of an object via copy constructor where neither the source nor the copied variable are modified before the variable goes out of scope. Rather than the copy, a reference to the source object could be used to save memory."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n int a;\n};\n\nint unnecessary_copy(A& x){\n auto y = x; // calls copy constructor\n return y.a; // y is not modified after copy, hence we could avoid the copy by adding & after auto as below\n}\n\nint use_reference_instead(A& x){\n auto& y = x; // copy the ref only\n return y.a;\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Assignment Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Intermediate" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary temporary copy of an intermediate object where copy is created to be passed down to a function unnecessarily. Instead, the intermediate object should either be moved into the callee or the type of the callee's parameter should be made ",(0,i.jsx)(n.code,{children:"const &"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A prime example of this occurs when we call a function with a call-by-value parameter as follows:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void callee(ExpensiveObject obj) {\n // ....\n}\n\nvoid caller() {\n callee(myExpensiveObj); // a copy of myExpensiveObj is created\n // the copy is destroyed right after the call \n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this case, when we call ",(0,i.jsx)(n.code,{children:"callee"}),", under the hood, a copy of the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is created to be passed to the function call. However, the copy might be unnecessary if"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"callee"})," doesn\u2019t modify its parameter \u2192 then we can change its type to ",(0,i.jsx)(n.code,{children:"const ExpensiveObject&"}),", getting rid of the copy at caller"]}),"\n",(0,i.jsxs)(n.li,{children:["even if ",(0,i.jsx)(n.code,{children:"callee"})," might modify the object, if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is never used later on, we can get rid of the copy by moving it instead: ",(0,i.jsx)(n.code,{children:"callee(std::move(myExpensiveObj))"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["The analysis is careful about suggesting moves blindly though: if the argument ",(0,i.jsx)(n.code,{children:"myExpensiveObj"})," is of type ",(0,i.jsx)(n.code,{children:"const & ExpensiveObject"})," then we also recommend that for move to work, const-reference needs to be removed."]}),"\n",(0,i.jsx)(n.p,{children:"PS: We check for other conditions on the argument here: e.g. it should be local to the procedure, as moving a non-local member might cause other memory correctness issues like use-after-move later on."}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Intermediate from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Movable" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy into a field where"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"the source is an rvalue-reference"}),"\n",(0,i.jsx)(n.li,{children:"the source is not modified before it goes out of scope or is destroyed."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that the copy can be modified since it has the ownership of the object."}),"\n",(0,i.jsx)(n.p,{children:"Fix: Rather than the copying into the field, the source should be moved into it."}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"struct A {\n std::vector vec;\n};\n\nclass Test {\n A mem_a;\n\n void unnecessary_copy(A&& src) {\n mem_a = src;\n // fix is to move as follows\n // mem_a = std::move(src);\n }\n\n};\n\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy to Optional" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary copy of an object via ",(0,i.jsx)(n.code,{children:"optional"})," value\nconstruction where the source is not modified before it goes out of scope. To avoid the copy, we\ncan move the source object or change the callee's type."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void get_optional_value(std::optional x) {}\n\nvoid pass_non_optional_value(A x) {\n get_optional_value(x);\n // fix is to move as follows\n // get_optional_value(std::move(x));\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy to Optional from Const" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Unnecessary Copy Return" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This is similar to ",(0,i.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),", but reported when a callee returns a copied value and it is not modified in its caller. We may be able to return const-ref typed value or try ",(0,i.jsx)(n.code,{children:"std::move"})," to avoid the copy."]}),"\n",(0,i.jsx)(n.p,{children:"For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"class MyClass {\n T v;\n public:\n T get() {\n return v; // v is copied here, which is avoidable.\n }\n};\n\nvoid caller(MyClass obj) {\n T x = obj.get();\n std::cout << x; // x is not modified.\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"pure_function",children:"PURE_FUNCTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Pure Function" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-purity",children:"purity"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This issue type indicates pure functions. For instance, below functions would be marked as pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"int local_write_pure(int x, int y) {\n int k = x + y;\n k++;\n return k;\n}\n\n// no change to outside state, the local allocation is ok.\nint local_alloc_pure(ArrayList list) {\n ArrayList list_new = new ArrayList();\n for (Integer el : list) {\n list_new.add(el);\n }\n return list_new.size();\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"However, the following ones would not be pure:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"void swap_impure(int[] array, int i, int j) {\n int tmp = array[i];\n array[i] = array[j]; // modifying the input array\n array[j] = tmp;\n}\n\nint a = 0;\nvoid set_impure(int x, int y) {\n a = x + y; //modifying a global variable\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"quandary_taint_error",children:"QUANDARY_TAINT_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Taint Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Generic taint error when nothing else fits."}),"\n",(0,i.jsx)(n.h2,{id:"regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Regex Op On Ui Thread" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A potentially costly operation on a regular expression occurs on the UI thread."}),"\n",(0,i.jsx)(n.h2,{id:"resource_leak",children:"RESOURCE_LEAK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Resource Leak" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Infer reports resource leaks in C, Objective-C and Java. In general, resources\nare entities such as files, sockets, connections, etc, that need to be closed\nafter being used."}),"\n",(0,i.jsx)(n.h3,{id:"resource-leak-in-c",children:"Resource leak in C"}),"\n",(0,i.jsx)(n.p,{children:"This is an example of a resource leak in C code:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:'-(void) resource_leak_bug {\n FILE *fp;\n fp=fopen("c:\\\\test.txt", "r"); // file opened and not closed.\n}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"resource-leak-in-java",children:"Resource leak in Java"}),"\n",(0,i.jsx)(n.p,{children:"For the remaining of this section, we will consider examples of resource leaks\nin Java code."}),"\n",(0,i.jsxs)(n.p,{children:["TIP: A common source of bugs is ",(0,i.jsx)("b",{children:"exceptions skipping past close()\nstatements"}),". That is the first thing to look for if INFER reports a potential\nresource leak."]}),"\n",(0,i.jsx)(n.h3,{id:"basics-and-standard-idiom",children:"Basics and Standard Idiom"}),"\n",(0,i.jsxs)(n.p,{children:["Some objects in Java, the ",(0,i.jsx)("i",{children:"resources"}),", are supposed to be closed when you\nstop using them, and failure to close is a ",(0,i.jsx)("i",{children:"resource leak"}),". Resources\ninclude input streams, output streams, readers, writers, sockets, http\nconnections, cursors, and json parsers."]}),"\n",(0,i.jsx)(n.p,{children:"The standard idiom is"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // Standard idiom\n Allocate resource\n try {\n do some stuff\n } finally {\n close resource\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"or more for example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Standard Idiom\n public static void foo () throws IOException{\n FileOutputStream fos = new FileOutputStream(new File("whatever.txt"));\n try {\n fos.write(7);\n } finally {\n fos.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"and you should use the standard idiom for the most part, when you don't want to\nreturn the resource to the surrounding context."}),"\n",(0,i.jsx)(n.p,{children:"Sometimes people just leave out close(), and that is a bug, but more typically\nexceptional paths are the root of the problem, as in"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // leak because of exception\n public static void foo () throws IOException {\n FileOutputStream fos = new FileOutputStream(new File("whatever.txt"));\n fos.write(7); //DOH! What if exception?\n fos.close();\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"where an exception in fos.write will cause execution to skip past the close()\nstatement."}),"\n",(0,i.jsx)(n.h4,{id:"multiple-resources-bugs",children:"Multiple Resources Bugs"}),"\n",(0,i.jsx)(n.p,{children:"We can deal with multiple resources correctly and simply just by nesting the\nstandard idiom."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources nested\n public static void foo() throws IOException {\n FileInputStream fis = new FileInputStream(new File("whatever.txt"));\n try {\n FileOutputStream fos = new FileOutputStream(new File("everwhat.txt"));\n try {\n fos.write(fis.read());\n } finally {\n fos.close();\n }\n } finally {\n fis.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"Bugs often occur when using multiple resources in other ways because of\nexceptions in close() methods. For example,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Classic Two Resources Bug\n public static void foo() throws IOException {\n FileInputStream fis = null;\n FileOutputStream fos = null;\n try {\n fis = new FileInputStream(new File("whatever.txt"));\n fos = new FileOutputStream(new File("everwhat.txt"));\n fos.write(fis.read());\n } finally {\n if (fis!=null) fis.close();\n if (fos!=null) fos.close();\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"Here, if there is an exception in the call to fis.close() execution will skip\npast fos.close(); a leak."}),"\n",(0,i.jsx)(n.p,{children:"Another way, besides the standard idiom, to deal with this problem is to swallow\nexceptions."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources Fix 1\n public static void foo() throws IOException {\n FileInputStream fis = null;\n FileOutputStream fos = null;\n try {\n fis = new FileInputStream(new File("whatever.txt"));\n fos = new FileOutputStream(new File("everwhat.txt"));\n fos.write(fis.read());\n } finally {\n try {\n if (fis!=null) fis.close();\n } catch (Exception e) {}; // Exception swallowing\n if (fos!=null) fos.close();\n }\n }\n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can also swallow the exception on the output stream. Some people prefer not\nto swallow output stream exceptions, and also flush before closing.\n",(0,i.jsx)(n.a,{href:"http://code.google.com/p/guava-libraries/issues/detail?id=1118",children:"http://code.google.com/p/guava-libraries/issues/detail?id=1118"})]}),"\n",(0,i.jsx)(n.p,{children:"Notice that the nested standard idiom does not need the checks for null, which\nare in there in this case to protect against the case when one of the\nallocations throws an exception, in which case one would get a\nNullPointerException."}),"\n",(0,i.jsx)(n.h3,{id:"nested_allocations",children:"Nested_Allocations"}),"\n",(0,i.jsx)(n.p,{children:"When a resource allocation is included as an argument to a constructor, if the\nconstructor fails it can leave an unreachable resource that no one can close."}),"\n",(0,i.jsx)(n.p,{children:"For example gzipOutputStream = new GZIPOutputStream(new FileOutputStream(out));\nis bad in case the outer constructor, GZIPOutputStream, throws an exception. In\nthat case, no one will have a hold of the FileOutputStream and so no one will be\nable to close it."}),"\n",(0,i.jsx)(n.p,{children:"In such a case you need to move the allocation the FileOutputStream out of the\nnested position and name it, so you are able to close if anything goes wrong\nduring execution of the GZIPOutputStream constructor."}),"\n",(0,i.jsx)(n.p,{children:"Here are resources that can throw exceptions i their constructor(s)."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"ObjectInputStream , ObjectOutputStream, PipedInputStream, PipedOutputStream,\nPipedReader, PipedWriter, JarInputStream, JarOutputStream, GZIPInputStream,\nGZIPOutputStream , ZipFile all throw IOException"}),"\n",(0,i.jsx)(n.li,{children:"PrintStream throws UnsupportedEncodingException"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The constructors for FileInputStream, FileOutputStream and RandomAccessFile\nthrow FileNotFoundException, but these cases are not problematic in the sense\nthat their arguments are not resources and so they do not cause the nested\nresource leak."}),"\n",(0,i.jsx)(n.h3,{id:"allocation-of-jsonparser-and-cursor-resources",children:"Allocation of JSonParser and Cursor resources"}),"\n",(0,i.jsx)(n.p,{children:'Some resources are created inside libraries instead of by "new".'}),"\n",(0,i.jsx)(n.p,{children:"Cursor is an interface, the actual resources are something like SQLiteCursor.\nSo, every time you call a function that returns a Cursor object, there is an\nallocation."}),"\n",(0,i.jsx)(n.p,{children:"For instance, in the functions from SQLiteDatabase query(\u2026) and rawQuery(\u2026)\nallocate a cursor resource. For SQLiteQueryBuilder, ContentProviderClient,\nContentResolver. MediaStore and DownloadManager it is only query(\u2026) Cursor\nobjects cursor created by these functions need to be closed (i.e.,\ncursor.close())."}),"\n",(0,i.jsx)(n.p,{children:"Similarly, JsonParser is an abstract class, and create a resource in functions\nfrom the class JsonFactory createParser(byte[] data) createParser(byte[] data,\nint offset, int len) createParser(String content) createParser(URL url)\ncreateParser(File f) JsonParser objects js created by these functions need to be\nclosed (jp.close()). On the other hand . JasonParsers gotten from\ncreateParser(InputStream in) and createParser(Reader r) give you JsonParsers\nthat don\u2019t need to be closed. This is because they receive the resource from\nsomewhere that will maintain the responsibility to close it."}),"\n",(0,i.jsx)(n.h3,{id:"escaping-resources-and-exceptions",children:"Escaping resources and exceptions"}),"\n",(0,i.jsx)(n.p,{children:"Sometimes you want to return a resource to the outside, in which case you should\nnot close it, but you still need to be careful of exceptions in case control\nskips past the return leaving no one to close. Here is a simple example of a\npositive use of escaping resources."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // An escaping resource, shouldn't close\n public BugReportAttachment createAttachment(File reportDirectory, String fileName)\n throws FileNotFoundException {\n File file = new File(reportDirectory, fileName);\n OutputStream stream = new FileOutputStream(file);\n return new BugReportAttachment(Uri.fromFile(file), stream);\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:["In this case it is intended that an object that wraps ",(0,i.jsx)(n.code,{children:"stream"})," is passed to the\ncaller of ",(0,i.jsx)(n.code,{children:"createAttachment"}),". You should certainly not close stream here,\nbecause it is being passed to the outside."]}),"\n",(0,i.jsx)(n.p,{children:"But for escaping resources like this you still need to be careful of exceptions.\nFor example, in"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" // An escaping resource, and a leak\n public BugReportAttachment createAttachment(File reportDirectory, String fileName)\n throws FileNotFoundException {\n File file = new File(reportDirectory, fileName);\n OutputStream stream = new FileOutputStream(file);\n stream.write(7);\n return new BugReportAttachment(Uri.fromFile(file), stream);\n }\n"})}),"\n",(0,i.jsx)(n.p,{children:"if stream.write(7) throws an exception, then no one will have a hold of stream,\nand no one will be able to close it; a leak."}),"\n",(0,i.jsx)(n.h3,{id:"java-7s-try-with-resources",children:"Java 7's try-with-resources"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"(For use with Java 7 only)"})}),"\n",(0,i.jsx)(n.p,{children:"Clearly, accounting for the ramifications of all the exceptional cases is\ncomplicated, and there is a better way in Java 7."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' // Two Resources Fix 2; via try-with-resources\n public static void foo() throws IOException {\n try (\n FileInputStream fis = new FileInputStream(new File("whatever.txt"));\n FileOutputStream fos = new FileOutputStream(new File("everwhat.txt"))\n ) {\n fos.write(fis.read());\n }\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:"All the complicated exceptional cases above are (apparently) covered by this\nconstruct, and the result is much simpler."}),"\n",(0,i.jsx)(n.p,{children:"So, if you are trying to fix a potential leak in code with multiples resources\nyou can go ahead and try to understand whether the potential leak is real. Or,\nif the code is complex and it is hard to figure out, it would be perfectly\nlegitimate to simply convert the code over to try-with-resources if you have\naccess to Java 7, so as to save yourself some brain-cycles. You will also end up\nwith cleaner code."}),"\n",(0,i.jsxs)(n.p,{children:["If try-with-resources is so great you should ",(0,i.jsx)("i",{children:"always"}),' use it. But you\nshouldn\'t\u2026 Try-with-resources gives resources static scoping, and works via a\nstack discipline. Sometimes, you want a resource to persist beyond scope, as in\nthe escaping example above. In an escaping example maybe you could refactor lots\nof code so that try-with-resources applies, and maybe you cannot in a sensible\nway. This just illustrates that, though you might hear people say that\ntry-with-resources "solves" the resource problem, it does not. It is very\nuseful, but you cannot use it blindly when you see a resource-allocation site.']}),"\n",(0,i.jsx)(n.h2,{id:"retain_cycle",children:"RETAIN_CYCLE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Retain Cycle" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A retain cycle is a situation when object A retains object B, and object B\nretains object A at the same time. Here is an example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n Child *child; // Instance variables are implicitly __strong\n}\n@end\n@interface Child : NSObject {\n Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.p,{children:'You can fix a retain cycle in ARC by using __weak variables or weak properties\nfor your "back links", i.e. links to direct or indirect parents in an object\nhierarchy:'}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"@class Child;\n@interface Parent : NSObject {\n Child *child;\n}\n@end\n@interface Child : NSObject {\n __weak Parent *parent;\n}\n@end\n"})}),"\n",(0,i.jsx)(n.h2,{id:"scope_leakage",children:"SCOPE_LEAKAGE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Scope Leakage" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-scope-leakage",children:"scope-leakage"}),"."]}),"\n",(0,i.jsx)(n.p,{children:'This issue type indicates that a class with scope annotation A stores a field\nwith whose (dynamic) type (or one of its super types) is annotated with scope\nB such that a scope nesting restriction is violated. By "stores", we mean\neither directly or transitively.'}),"\n",(0,i.jsx)(n.p,{children:"A configuration is used to list the set of scopes and the must-not-hold relation."}),"\n",(0,i.jsx)(n.p,{children:"In the following Java example, the set of scopes is Outer and Inner, and the must-not-hold\nrelation is simply {(Outer, Inner)}:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:"@ScopeType(value = Outer.class)\nclass ClassOfOuterScope {\n final ClassOfInner c = new ClassOfInner(); // <-- warn here that ClassOfInner would leak.\n}\n\n@ScopeType(value = Inner.class)\nclass ClassOfInner {}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Here is a more detailed description of the analysis."}),"\n",(0,i.jsx)(n.p,{children:'This analysis operates over Java bytecode. It assumes that types (classes, interfaces, enums,\netc.) may be annotated with so-called scope annotations. The analysis is parameterized by a set\nof scopes and a "must-not-hold" relation over pairs of scopes, which it reads from a\nconfiguration file.'}),"\n",(0,i.jsx)(n.p,{children:'The analysis aims to detect violations of the following property: if there exist a path of\nfields from object OA to object OB and the type of OA (or one of its super-types) is annotated\nwith scope SA and the type of OB (or one of its super-types) is annotated with scope SB then\nmust-not-hold(SA, SB) must be false. Intuitively, the given objects have different scopes that\nshould not be nested, for example, different intended lifetimes, and a forbidden path from OA to\nOB results in OB "leaking" out of the scope SA.'}),"\n",(0,i.jsx)(n.p,{children:'The implementation reads a configuration to determine a list of (scope) "generators" for each\ntype of scope and a scope class for each type of scope. A generator for a scope type SA is given\nby the name of a class and a list of methods where it is understood that any of the methods\nlisted for the given class returns an object that is known to have scope SA. (This can be seen\nas a form of lightweight modeling.) A scope class is the name of the class that represents a\ngiven scope.'}),"\n",(0,i.jsx)(n.h2,{id:"sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sensitive Data Flow" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A flow of sensitive data was detected from a source."}),"\n",(0,i.jsx)(n.h2,{id:"shell_injection",children:"SHELL_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Shell Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Environment variable or file data flowing to shell."}),"\n",(0,i.jsx)(n.h2,{id:"shell_injection_risk",children:"SHELL_INJECTION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Shell Injection Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Code injection if the caller of the endpoint doesn't sanitize on its end."}),"\n",(0,i.jsx)(n.h2,{id:"sql_injection",children:"SQL_INJECTION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sql Injection" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted and unescaped data flows to SQL."}),"\n",(0,i.jsx)(n.h2,{id:"sql_injection_risk",children:"SQL_INJECTION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Sql Injection Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted and unescaped data flows to SQL."}),"\n",(0,i.jsx)(n.h2,{id:"stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Stack Variable Address Escape" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Reported when an address pointing into the stack of the current\nfunction will escape to its calling context. Such addresses will\nbecome invalid by the time the function actually returns so are\npotentially dangerous."}),"\n",(0,i.jsx)(n.p,{children:"For example, directly returning a pointer to a local variable:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-C",children:'int* foo() {\n int x = 42;\n return &x; // <-- warn here that "&x" will escape\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"starvation",children:"STARVATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "UI Thread Starvation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"This error is reported in Java, and specifically on Android. These reports are\ntriggered when a method that runs on the UI thread may block, thus potentially\nleading to an Application Not Responding error."}),"\n",(0,i.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,i.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,i.jsxs)(n.li,{children:["The method or its callees call a ",(0,i.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The issue is reported when a method deemed to run on the UI thread"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Makes a method call which may block."}),"\n",(0,i.jsx)(n.li,{children:"Takes a lock, and another thread takes the same lock, and before releasing it,\nmakes a call that may block."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Calls that may block are considered:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Certain I/O calls."}),"\n",(0,i.jsxs)(n.li,{children:["Two way ",(0,i.jsx)(n.code,{children:"Binder.transact"})," calls."]}),"\n",(0,i.jsx)(n.li,{children:"Certain OS calls."}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"Future"})," or ",(0,i.jsx)(n.code,{children:"AsyncTask"})," calls to ",(0,i.jsx)(n.code,{children:"get"})," without timeouts, or with too large\ntimeouts."]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress starvation reports in a method ",(0,i.jsx)(n.code,{children:"m()"})," use the\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STARVATION")'})," annotation, as follows:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("STARVATION")\n public void m() {\n ...\n }\n'})}),"\n",(0,i.jsxs)(n.p,{children:["To signal to Infer that a method does not perform any blocking calls, despite\nappearences, you can use the ",(0,i.jsx)(n.code,{children:"@NonBlocking"})," annotation:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-java",children:" import com.facebook.infer.annotation.NonBlocking;\n\n @NonBlocking\n public void m() {\n ...\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:["This instructs Infer to filter out any potentially blocking calls in ",(0,i.jsx)(n.code,{children:"m()"}),"\n(also, transitively), and thus any other method can expect no starvation reports\ndue to a call to ",(0,i.jsx)(n.code,{children:"m()"}),". You will need to set up your class path appropriately to\ninclude the JAR files in ",(0,i.jsx)(n.code,{children:"infer/annotations"})," for this annotation to work."]}),"\n",(0,i.jsx)(n.h2,{id:"static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Static Initialization Order Fiasco" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-siof",children:"siof"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This error is reported in C++. It fires when the initialization of a static\nvariable ",(0,i.jsx)(n.code,{children:"A"}),", accesses a static variable ",(0,i.jsx)(n.code,{children:"B"})," from another translation unit\n(usually another ",(0,i.jsx)(n.code,{children:".cpp"})," file). There are no guarantees whether ",(0,i.jsx)(n.code,{children:"B"})," has been\nalready initialized or not at that point."]}),"\n",(0,i.jsxs)(n.p,{children:["For more technical definition and techniques to avoid/remediate, see the\n",(0,i.jsx)(n.a,{href:"https://isocpp.org/wiki/faq/ctors#static-init-order",children:"FAQ"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strict_mode_violation",children:"STRICT_MODE_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Strict Mode Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Android has a feature called\n",(0,i.jsx)(n.a,{href:"https://developer.android.com/reference/android/os/StrictMode",children:"strict mode"}),",\nwhich if enabled, will flag the occasions where the main thread makes a call\nthat results in disk I/O, waiting on a network socket, etc. The analysis\ncatching starvation errors and deadlocks (the ",(0,i.jsx)(n.code,{children:"--starvation"})," analysis) has the\nability to statically detect such violations."]}),"\n",(0,i.jsxs)(n.p,{children:["To suppress this warning, it's enough to annotate the offending method with\n",(0,i.jsx)(n.code,{children:'@SuppressLint("STRICT_MODE_VIOLATION")'}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "StrongSelf Not Checked" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This checks reports a potential issue when a block captures ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),"),\nthen one assigns this pointer to a local variable ",(0,i.jsx)(n.code,{children:"strongSelf"})," inside the block and uses this variable\nwithout checking first whether it is ",(0,i.jsx)(n.code,{children:"nil"}),". The problem here is that the weak pointer could be ",(0,i.jsx)(n.code,{children:"nil"})," at\nthe time when the block is executed. So, the correct usage is to first check whether ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a valid\npointer, and then use it."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n int y = strongSelf->x;\n ...\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action:"}),"\nAdd a check for ",(0,i.jsx)(n.code,{children:"nil"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:"__weak __typeof(self) weakSelf = self;\n int (^my_block)() = ^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n int y = strongSelf->x;\n ...\n }\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,i.jsx)(n.code,{children:"strongSelf"})," is a local variable to the block, so the check supports any name given to\na local strong pointer that has been assigned ",(0,i.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"taint_error",children:"TAINT_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Taint Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A taint flow was detected from a source to a sink"}),"\n",(0,i.jsx)(n.h2,{id:"thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Thread Safety Violation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["This warning indicates a potential data race in Java. The analyser is called\nRacerD and this section gives brief but a mostly complete description of its\nfeatures. See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"RacerD page"})," for more in-depth information and\nexamples."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-what-is-a-data-race",children:"Thread-safety: What is a data race"}),"\n",(0,i.jsx)(n.p,{children:"Here a data race is a pair of accesses to the same member field such that:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"at least one is a write, and,"}),"\n",(0,i.jsx)(n.li,{children:"at least one occurs without any lock synchronization, and,"}),"\n",(0,i.jsx)(n.li,{children:"the two accesses occur on threads (if known) which can run in parallel."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-potential-fixes",children:"Thread-safety: Potential fixes"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Synchronizing the accesses (using the ",(0,i.jsx)(n.code,{children:"synchronized"})," keyword, thread-exclusion\nsuch as atomic objects, ",(0,i.jsx)(n.code,{children:"volatile"})," etc)."]}),"\n",(0,i.jsx)(n.li,{children:"Making an offending method private -- this will exclude it from being checked\nat the top level, though it will be checked if called by a public method which\nmay itself, e.g., hold a lock when calling it."}),"\n",(0,i.jsxs)(n.li,{children:["Putting the two accesses on the same thread, e.g., by using ",(0,i.jsx)(n.code,{children:"@MainThread"})," or\n",(0,i.jsx)(n.code,{children:"@ThreadConfined"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-conditions-checked-before-reporting",children:"Thread-safety: Conditions checked before reporting"}),"\n",(0,i.jsxs)(n.p,{children:["The class and method are not marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe(enableChecks = false)"}),", and,"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The method is declared ",(0,i.jsx)(n.code,{children:"synchronized"}),", or employs (non-transitively) locking,\nor,"]}),"\n",(0,i.jsxs)(n.li,{children:["The class is not marked ",(0,i.jsx)(n.code,{children:"@NotThreadSafe"}),", and,","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The class/method is marked ",(0,i.jsx)(n.code,{children:"@ThreadSafe,"})," or one of the configured synonyms\nin ",(0,i.jsx)(n.code,{children:".inferconfig"}),", or,"]}),"\n",(0,i.jsx)(n.li,{children:"A parent class, or an override method are marked with the above annotations."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["NB currently RacerD ",(0,i.jsxs)(n.strong,{children:["does not take into account ",(0,i.jsx)(n.code,{children:"@GuardedBy"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-thread-annotations-recognized-by-racerd",children:"Thread-safety: Thread annotations recognized by RacerD"}),"\n",(0,i.jsxs)(n.p,{children:["These class and method annotations imply the method is on the main thread:\n",(0,i.jsx)(n.code,{children:"@MainThread"}),", ",(0,i.jsx)(n.code,{children:"@UiThread"})]}),"\n",(0,i.jsxs)(n.p,{children:["These method annotations imply the method is on the main thread: ",(0,i.jsx)(n.code,{children:"@OnBind"}),",\n",(0,i.jsx)(n.code,{children:"@OnEvent"}),", ",(0,i.jsx)(n.code,{children:"@OnMount"}),", ",(0,i.jsx)(n.code,{children:"@OnUnbind"}),", ",(0,i.jsx)(n.code,{children:"@OnUnmount"})]}),"\n",(0,i.jsx)(n.p,{children:"Both classes of annotations work through the inheritance tree (i.e. if a parent\nclass or method is marked with one of these annotations, so is the child class /\nmethod override)."}),"\n",(0,i.jsxs)(n.p,{children:["In addition to these, RacerD recognizes many lifecycle methods as necessarily\nrunning on the main thread, eg ",(0,i.jsx)(n.code,{children:"Fragment.onCreate"})," etc."]}),"\n",(0,i.jsxs)(n.p,{children:["Finally, the thread status of being on the main thread propagates backwards\nthrough the call graph (ie if ",(0,i.jsx)(n.code,{children:"foo"})," calls ",(0,i.jsx)(n.code,{children:"bar"})," and ",(0,i.jsx)(n.code,{children:"bar"})," is marked ",(0,i.jsx)(n.code,{children:"@UiThtread"}),"\nthen ",(0,i.jsx)(n.code,{children:"foo"})," is automatically considered on the main thread too). Calling\n",(0,i.jsx)(n.code,{children:"assertMainThread"}),", ",(0,i.jsx)(n.code,{children:"assertOnUiThread"}),", ",(0,i.jsx)(n.code,{children:"checkOnMainThread"})," has the same effect."]}),"\n",(0,i.jsxs)(n.p,{children:["NB RacerD currently ",(0,i.jsxs)(n.strong,{children:["does not recognize ",(0,i.jsx)(n.code,{children:"@WorkerThread"}),", ",(0,i.jsx)(n.code,{children:"@BinderThread"})," or\n",(0,i.jsx)(n.code,{children:"@AnyThread"})]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"thread-safety-other-annotations-and-what-they-do",children:"Thread-safety: Other annotations and what they do"}),"\n",(0,i.jsxs)(n.p,{children:["These annotations can be found at ",(0,i.jsx)(n.code,{children:"com.facebook.infer.annotation.*"}),"."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@Functional"})," This is a method annotation indicating the method always returns\nthe same value. When a method ",(0,i.jsx)(n.code,{children:"foo"})," is annotated ",(0,i.jsx)(n.code,{children:"@Functional"}),", RacerD will\nignore any writes of the return value of ",(0,i.jsx)(n.code,{children:"foo"}),". For example, in\n",(0,i.jsx)(n.code,{children:"this.x = foo()"}),", the write to ",(0,i.jsx)(n.code,{children:"this.x"})," is ignored. The reasoning is that if\nthe method returns the same value whenever it's called, any data race on\n",(0,i.jsx)(n.code,{children:"this.x"})," is benign, if that is the only write."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ThreadConfined"})," This is a class/method/field annotation which takes a single\nparameter which can be ",(0,i.jsx)(n.code,{children:"UI"}),", ",(0,i.jsx)(n.code,{children:"ANY"})," or a user chosen string. It indicates to\nRacerD a thread identifier for the class/method/field. Thus,\n",(0,i.jsx)(n.code,{children:"@ThreadConfined(UI)"})," is equivalent to ",(0,i.jsx)(n.code,{children:"@UiThread"}),", and ",(0,i.jsx)(n.code,{children:"@ThreadConfined(ANY)"}),"\nis equivalent to not having the annotation at all, for classes and methods.\nWhen this annotation is applied to a field it instructs Infer to assume\n(without checking) that all accesses to that field are made on the same thread\n(and can, therefore, not race by definition). The intention is that RacerD\nuses that to detect exclusion between accesses occurring on the same thread.\nHowever, only the UI thread is supported at this time, and any user provided\nvalue is considered equal to ",(0,i.jsx)(n.code,{children:"UI"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@VisibleForTesting"})," A method annotation making Infer consider the method as\neffectively ",(0,i.jsx)(n.code,{children:"private"}),". This means it will not be checked for races against\nother non-private methods of the class, but only if called by one."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@ReturnsOwnership"})," A method annotation indicating that the method returns a\nfreshly owned object. Accesses to the returned value will not be considered\nfor data races, as the object is in-effect unique and not accessible yet from\nother threads. The main utility of this annotation is in interfaces, where\nInfer cannot look up the implementation and decide for itself."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error",children:"TOPL_ERROR"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Topl Error" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"A violation of a Topl property (user-specified).\nThere is an execution path in the code that drives a Topl property from a start state to an error state."}),"\n",(0,i.jsx)(n.p,{children:"This indicates that the code has a user-defined undesired behavior."}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.a,{href:"/docs/next/checker-topl##what-is-it",children:"Topl"})," for an example"]}),"\n",(0,i.jsx)(n.h2,{id:"topl_error_latent",children:"TOPL_ERROR_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Topl Error Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#topl_error",children:"TOPL_ERROR"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"uninitialized_value",children:"UNINITIALIZED_VALUE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Uninitialized Value" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-uninit",children:"uninit"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The code uses a variable that has not been initialized, leading to unpredictable or unintended results."}),"\n",(0,i.jsx)(n.p,{children:"Using uninitialized values can lead to undefined behaviors possibly resulting in crashes, security failures and invalid results."}),"\n",(0,i.jsx)(n.p,{children:"This can easily be fixed by assigning all variables to an initial value when declaring them."}),"\n",(0,i.jsx)(n.p,{children:"This, for example, in C:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-c",children:"struct coordinates {\n int x;\n int y;\n};\n\nvoid foo() {\n struct coordinates c;\n c.x = 42;\n c.y++; // uninitialized value c.y!\n\n int z;\n if (z == 0) { // uninitialized value z!\n // something\n }\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_buffer_access",children:"UNTRUSTED_BUFFER_ACCESS"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Buffer Access" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to buffer."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_deserialization",children:"UNTRUSTED_DESERIALIZATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Deserialization" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled deserialization."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_deserialization_risk",children:"UNTRUSTED_DESERIALIZATION_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Deserialization Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled deserialization"}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_environment_change_risk",children:"UNTRUSTED_ENVIRONMENT_CHANGE_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Environment Change Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled environment mutation."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_file",children:"UNTRUSTED_FILE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted File" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled file creation; may be vulnerable to path traversal and more."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_file_risk",children:"UNTRUSTED_FILE_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted File Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"User-controlled file creation; may be vulnerable to path traversal and more."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_heap_allocation",children:"UNTRUSTED_HEAP_ALLOCATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Heap Allocation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to heap allocation. this can cause crashes or DOS."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_intent_creation",children:"UNTRUSTED_INTENT_CREATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Intent Creation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Creating an Intent from user-controlled data."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_url_risk",children:"UNTRUSTED_URL_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Url Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted flag, environment variable, or file data flowing to URL."}),"\n",(0,i.jsx)(n.h2,{id:"untrusted_variable_length_array",children:"UNTRUSTED_VARIABLE_LENGTH_ARRAY"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Untrusted Variable Length Array" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data of any kind flowing to stack buffer allocation. Trying to allocate a stack buffer that's too large will cause a stack overflow."}),"\n",(0,i.jsx)(n.h2,{id:"user_controlled_sql_risk",children:"USER_CONTROLLED_SQL_RISK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "User Controlled Sql Risk" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-quandary",children:"quandary"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Untrusted data flows to SQL (no injection risk)."}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete",children:"USE_AFTER_DELETE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Delete" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"delete"})," in C++ is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Delete Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_delete",children:"USE_AFTER_DELETE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free",children:"USE_AFTER_FREE"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Free" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,i.jsx)(n.code,{children:"free"})," in C is dereferenced."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_free_latent",children:"USE_AFTER_FREE_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Free Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_free",children:"USE_AFTER_FREE"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime",children:"USE_AFTER_LIFETIME"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Lifetime" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The lifetime of an object has ended but that object is being\naccessed. For example, the address of a variable holding a C++ object\nis accessed after the variable has gone out of scope:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:"void foo() {\n X* p;\n { // new scope\n X x = X();\n p = &x;\n } // x has gone out of scope\n p->method(); // ERROR: you should not access *p after x has gone out of scope\n}\n"})}),"\n",(0,i.jsx)(n.h2,{id:"use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Use After Lifetime Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#use_after_lifetime",children:"USE_AFTER_LIFETIME"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation",children:"VECTOR_INVALIDATION"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Vector Invalidation" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["An address pointing into a C++ ",(0,i.jsx)(n.code,{children:"std::vector"})," might have become\ninvalid. This can happen when an address is taken into a vector, then\nthe vector is mutated in a way that might invalidate the address, for\nexample by adding elements to the vector, which might trigger a\nre-allocation of the entire vector contents (thereby invalidating the\npointers into the previous location of the contents)."]}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-cpp",children:'void deref_vector_element_after_push_back_bad(std::vector& vec) {\n int* elt = &vec[1];\n vec.push_back(42); // if the array backing the vector was full already, this\n // will re-allocate it and copy the previous contents\n // into the new array, then delete the previous array\n std::cout << *y << "\\n"; // bad: elt might be invalid\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Vector Invalidation Latent" by ',(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["A latent ",(0,i.jsx)(n.a,{href:"#vector_invalidation",children:"VECTOR_INVALIDATION"}),". See the ",(0,i.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"weak_self_in_no_escape_block",children:"WEAK_SELF_IN_NO_ESCAPE_BLOCK"}),"\n",(0,i.jsxs)(n.p,{children:['Reported as "Weak Self In No Escape 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 reports when ",(0,i.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,i.jsx)(n.code,{children:"self"}),') is used in\na block, and this block is passed to a "no escaping" method. This means that\nthe block passed to that method won\'t be leaving the current scope, this is\nmarked with the annotation ',(0,i.jsx)(n.code,{children:"NS_NOESCAPE"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:['The issue here is that, because the block is "no escaping", there is no need to use\n',(0,i.jsx)(n.code,{children:"weakSelf"})," and ",(0,i.jsx)(n.code,{children:"strongSelf"})," but we can just use ",(0,i.jsx)(n.code,{children:"self"}),". This has the advantage of\nnot needing to deal with the added complexity of weak pointers, and it simplifies the\ncode."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n [self foo:^() { //foo's first parameter is annotates with `NS_NOESCAPE`\n [weakSelf bar];\n }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,i.jsxs)(n.p,{children:["Replace ",(0,i.jsx)(n.code,{children:"weakSelf"})," with ",(0,i.jsx)(n.code,{children:"self"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-objectivec",children:" [self foo:^() {\n [self bar];\n }];\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,i.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,i.jsx)(n.code,{children:"self"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,r.M)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2172:(e,n,s)=>{s.d(n,{I:()=>l,M:()=>a});var i=s(1504);const r={},t=i.createContext(r);function a(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.192018d4.js b/assets/js/runtime~main.040defb2.js similarity index 98% rename from assets/js/runtime~main.192018d4.js rename to assets/js/runtime~main.040defb2.js index 2188e102a6a..c6d42bdbb50 100644 --- a/assets/js/runtime~main.192018d4.js +++ b/assets/js/runtime~main.040defb2.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,f,d,b={},c={};function r(e){var a=c[e];if(void 0!==a)return a.exports;var f=c[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,d,b)=>{if(!f){var c=1/0;for(i=0;i=b)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[f,d,b]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var b=Object.create(null);r.r(b);var c={};a=a||[null,f({}),f([]),f(f)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,r.d(b,c),b},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({112:"e44e3f47",172:"21614072",188:"bab022f4",208:"184ad633",264:"3f2a1ecb",379:"9258f162",644:"3c741b47",724:"f5ff54f0",820:"58de4400",904:"3c653e3b",920:"16fe8a4c",956:"cd83de9e",980:"ceca19cd",1008:"1460e89b",1080:"9242256d",1085:"1fdfdeaa",1088:"219c4568",1116:"e2e89445",1200:"bc3f1a98",1240:"e15bcb33",1260:"5c9e12d1",1272:"b4e1da39",1292:"dc4598d0",1352:"0346afaa",1412:"7efbfa7e",1440:"c7401661",1624:"041e4035",1660:"70793eb2",1672:"21a9d6ed",1692:"f8092feb",1728:"d9e16301",1792:"671939c9",1912:"64f1f19c",2008:"9118549b",2012:"af0d8a1e",2068:"00d3276d",2096:"a5a260f1",2124:"c2d67624",2200:"45d37095",2356:"79263788",2416:"6baf1826",2448:"f5711d0d",2632:"c4f5d8e4",2708:"9d4bdb35",2728:"937dc5a6",2756:"3423820d",2760:"420497a2",2762:"413f2abb",2764:"c027c09e",2872:"9a49882e",2900:"be77d225",3016:"def5ef2c",3043:"3caf9b73",3044:"509dc7bf",3048:"99c7964b",3104:"ddb8503b",3116:"bbdc39ec",3128:"12577cfd",3132:"ae565638",3200:"f278ac2c",3280:"e6b9ef91",3292:"fa38ac94",3372:"fa9ab54d",3448:"cbb882cb",3596:"a33b6a74",3600:"e66621bc",3612:"bd470307",3796:"1dbe42a7",3840:"ab17452f",3876:"1db0afb7",4020:"fe661d8a",4072:"495e5e06",4152:"aae2c465",4156:"af0818da",4184:"9d221b96",4217:"6021085e",4220:"a78783ee",4304:"5e95c892",4308:"a373fd77",4440:"f769b3fd",4486:"64cca8ef",4616:"c14a26e3",4666:"a94703ab",4724:"4c2546f9",4824:"6297ff83",4856:"ca86781b",4976:"a6aa9e1f",5008:"5f403532",5048:"c26add1d",5192:"da41ed28",5244:"3eac2097",5336:"1d8647da",5388:"c71502c9",5505:"5a5dcc21",5512:"814f3328",5516:"c8a5dae5",5584:"8a061d83",5680:"acaf655c",5696:"935f2afb",5708:"7d50aa41",5752:"7f661f82",5840:"71a2656f",5868:"c2f60cfc",5920:"eb0c92c1",6040:"7b1f0035",6068:"df12ff2a",6164:"8fdeae25",6180:"25a5a20c",6209:"49bfadd9",6292:"b2b675dd",6322:"15a3954c",6344:"ccc49370",6416:"92185360",6452:"0fe8a02a",6500:"a7bd4aaa",6576:"5bb07cf5",6608:"b784ffba",6680:"f5cfbeab",6714:"4dac5fec",6730:"57bcddd6",6732:"bf6aacca",6748:"bc318449",6752:"17896441",6828:"43455a69",6868:"31868bec",6880:"b2f554cd",6952:"ff0352e3",7012:"56ebd09a",7028:"9e4087bc",7136:"df53045f",7180:"99b7fc87",7192:"3d9729af",7208:"aaff9110",7296:"0ac93784",7332:"c222a988",7552:"a6f42423",7568:"cb9da62d",7664:"62e81aa6",7712:"6d752ef5",7724:"2ba1d2b8",7840:"128c6d36",7848:"07d14bbd",7920:"3c055f5e",7948:"1df9637e",7952:"18328e9e",7996:"acb2d06a",8008:"556d04db",8012:"5bb3de56",8176:"aa0b35eb",8252:"b5b9c8e0",8263:"e305a15c",8372:"8919ea97",8384:"06d8773d",8392:"a2bed8f0",8444:"8db808e7",8448:"a9946d6a",8528:"0c0efcaa",8532:"a90afd08",8544:"c359af60",8601:"e6b91a21",8608:"c412bf64",8768:"491a3217",8808:"9702a600",8858:"a02168a2",8906:"33776668",8916:"4fefa35c",8928:"1906a68b",8934:"b065408b",8980:"abc9d724",9032:"e0f83a1d",9064:"62b182e9",9096:"879f7a7c",9198:"d47ba782",9258:"bd8da646",9396:"e436f9fb",9400:"3eb0a99f",9412:"c8131338",9456:"34fbd09a",9648:"1a4e3797",9656:"e9325e77",9700:"293e08e8",9728:"04f8d6af",9792:"1c7a9c9f",9808:"b9f8aa82"}[e]||e)+"."+{112:"ffbbd5a2",172:"3d6916df",188:"79e4a80e",208:"eea5a87b",264:"fccfb010",379:"0e4d7b0a",606:"027c6754",644:"dd600205",724:"ef4e73e6",820:"0d6348ab",904:"d8e59a5c",920:"68a01e73",956:"1cb8b261",980:"a309122e",1008:"725073a1",1080:"528a43fb",1085:"8a3c90e1",1088:"fc2e112f",1116:"0e7edc0d",1200:"390cae50",1240:"cc1b4e88",1260:"b3bb7e41",1272:"2099fa4d",1292:"6d320dd3",1352:"2a632c4a",1412:"40b6eb7f",1440:"be188dac",1624:"27c01a88",1660:"2305c43d",1672:"fef644e3",1676:"a0d9bd55",1692:"57dc7e74",1728:"32b3bbc5",1792:"7fe26650",1912:"aa3ea31b",2008:"591896b0",2012:"646cf20d",2068:"03674a6d",2096:"f47494d4",2124:"b332c10d",2200:"0ba3ee42",2356:"c00c6910",2416:"2e1ea009",2448:"f7fce5c6",2528:"2436a084",2632:"45587cbf",2708:"132887ba",2728:"7a7e0323",2756:"a542dc61",2760:"e97e3bca",2762:"a3457e4c",2764:"4fc4c65f",2872:"c1ef5e32",2900:"6d04e5db",3016:"240a2ea8",3043:"e8e1a67e",3044:"1f608ccf",3048:"b3616e44",3104:"8d473c1e",3116:"2ba35945",3128:"8dddd7b3",3132:"f2fe2dd6",3200:"124ee451",3280:"f3c9d5af",3292:"73f3b653",3372:"fd1aa6a5",3448:"141e3db8",3596:"2ef6d204",3600:"5479a356",3612:"b8b78b42",3796:"a018a53d",3840:"3d5798e8",3876:"966742a8",4020:"a783da53",4072:"1bf8fe81",4152:"76957a46",4156:"2b0ca4a0",4184:"2ce25209",4217:"454fc3dc",4220:"399d3336",4304:"84883c70",4308:"50ac0805",4440:"6f9bafa0",4486:"47a97907",4552:"a809afa9",4616:"a5d26616",4666:"15af1f33",4724:"aa757dad",4824:"ba2e3f26",4856:"abeae509",4976:"2123d972",5008:"e45b0829",5048:"64a8d6d6",5192:"18b098d4",5244:"20f274f3",5336:"913a6527",5388:"a515464f",5505:"0210552f",5512:"8f5f87e7",5516:"5dadb0ab",5584:"d6beed89",5680:"d93f86b2",5696:"f9b2dd0c",5708:"76d6ebf0",5752:"36188801",5840:"d89b2af4",5868:"c2fd70a8",5920:"08bdd6e6",6040:"f46eb7ff",6068:"2ada05aa",6164:"bf070cb1",6180:"58d19b0c",6209:"8ce1a55c",6292:"1a619e45",6322:"da84e45e",6344:"79bdc319",6416:"62040dd7",6452:"9a882eef",6500:"ad11e11e",6576:"2d190a20",6608:"157cb050",6680:"8aceb2e0",6714:"4d9bde8d",6730:"5a4351c7",6732:"52379e0a",6748:"0acbe71c",6752:"ff15626b",6828:"ef40ff61",6868:"a2757938",6880:"bf75ef81",6952:"452e946b",7012:"8d1bf24f",7028:"e5742792",7136:"d1effc72",7180:"fd1ec705",7192:"f3228e08",7208:"8ee7db0a",7296:"141b2ea4",7332:"c8e180b7",7552:"45269320",7568:"c7d307bc",7664:"0d34f5ce",7712:"08611302",7724:"ddfb9119",7840:"6a105ea1",7848:"cb4af53a",7920:"104ed9fb",7948:"c9dfcd9d",7952:"d67c2c99",7996:"3da611ed",8008:"faf8a5ff",8012:"5e6c7cc5",8176:"f5d90ee0",8252:"f9249c3a",8263:"bd5a9ce2",8372:"9362dd44",8384:"b5758238",8392:"31624d4e",8444:"92e5af8b",8448:"081419be",8528:"993152bb",8532:"25cd3588",8544:"5a432b21",8601:"8a291491",8608:"b0e14a54",8768:"0ca8966a",8808:"1e2ebe76",8858:"dd051560",8879:"fbade3c5",8906:"599a6778",8916:"39c80c62",8928:"2a1eef90",8934:"2540184c",8980:"7b4df509",9032:"b75166be",9064:"de7ab418",9096:"312e269b",9116:"f0ae5377",9198:"b0e2468a",9258:"1266cf6c",9396:"644a2877",9400:"91186561",9412:"ca0da140",9456:"3daf123e",9648:"67f3f595",9656:"166166de",9700:"7411a2d9",9728:"1acbacea",9792:"a953a687",9808:"cc78e901"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},r.l=(e,a,f,b)=>{if(d[e])d[e].push(a);else{var c,t;if(void 0!==f)for(var o=document.getElementsByTagName("script"),n=0;n{c.onerror=c.onload=null,clearTimeout(l);var b=d[e];if(delete d[e],c.parentNode&&c.parentNode.removeChild(c),b&&b.forEach((e=>e(f))),a)return a(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=u.bind(null,c.onerror),c.onload=u.bind(null,c.onload),t&&document.head.appendChild(c)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"6752",21614072:"172",33776668:"8906",79263788:"2356",92185360:"6416",e44e3f47:"112",bab022f4:"188","184ad633":"208","3f2a1ecb":"264","9258f162":"379","3c741b47":"644",f5ff54f0:"724","58de4400":"820","3c653e3b":"904","16fe8a4c":"920",cd83de9e:"956",ceca19cd:"980","1460e89b":"1008","9242256d":"1080","1fdfdeaa":"1085","219c4568":"1088",e2e89445:"1116",bc3f1a98:"1200",e15bcb33:"1240","5c9e12d1":"1260",b4e1da39:"1272",dc4598d0:"1292","0346afaa":"1352","7efbfa7e":"1412",c7401661:"1440","041e4035":"1624","70793eb2":"1660","21a9d6ed":"1672",f8092feb:"1692",d9e16301:"1728","671939c9":"1792","64f1f19c":"1912","9118549b":"2008",af0d8a1e:"2012","00d3276d":"2068",a5a260f1:"2096",c2d67624:"2124","45d37095":"2200","6baf1826":"2416",f5711d0d:"2448",c4f5d8e4:"2632","9d4bdb35":"2708","937dc5a6":"2728","3423820d":"2756","420497a2":"2760","413f2abb":"2762",c027c09e:"2764","9a49882e":"2872",be77d225:"2900",def5ef2c:"3016","3caf9b73":"3043","509dc7bf":"3044","99c7964b":"3048",ddb8503b:"3104",bbdc39ec:"3116","12577cfd":"3128",ae565638:"3132",f278ac2c:"3200",e6b9ef91:"3280",fa38ac94:"3292",fa9ab54d:"3372",cbb882cb:"3448",a33b6a74:"3596",e66621bc:"3600",bd470307:"3612","1dbe42a7":"3796",ab17452f:"3840","1db0afb7":"3876",fe661d8a:"4020","495e5e06":"4072",aae2c465:"4152",af0818da:"4156","9d221b96":"4184","6021085e":"4217",a78783ee:"4220","5e95c892":"4304",a373fd77:"4308",f769b3fd:"4440","64cca8ef":"4486",c14a26e3:"4616",a94703ab:"4666","4c2546f9":"4724","6297ff83":"4824",ca86781b:"4856",a6aa9e1f:"4976","5f403532":"5008",c26add1d:"5048",da41ed28:"5192","3eac2097":"5244","1d8647da":"5336",c71502c9:"5388","5a5dcc21":"5505","814f3328":"5512",c8a5dae5:"5516","8a061d83":"5584",acaf655c:"5680","935f2afb":"5696","7d50aa41":"5708","7f661f82":"5752","71a2656f":"5840",c2f60cfc:"5868",eb0c92c1:"5920","7b1f0035":"6040",df12ff2a:"6068","8fdeae25":"6164","25a5a20c":"6180","49bfadd9":"6209",b2b675dd:"6292","15a3954c":"6322",ccc49370:"6344","0fe8a02a":"6452",a7bd4aaa:"6500","5bb07cf5":"6576",b784ffba:"6608",f5cfbeab:"6680","4dac5fec":"6714","57bcddd6":"6730",bf6aacca:"6732",bc318449:"6748","43455a69":"6828","31868bec":"6868",b2f554cd:"6880",ff0352e3:"6952","56ebd09a":"7012","9e4087bc":"7028",df53045f:"7136","99b7fc87":"7180","3d9729af":"7192",aaff9110:"7208","0ac93784":"7296",c222a988:"7332",a6f42423:"7552",cb9da62d:"7568","62e81aa6":"7664","6d752ef5":"7712","2ba1d2b8":"7724","128c6d36":"7840","07d14bbd":"7848","3c055f5e":"7920","1df9637e":"7948","18328e9e":"7952",acb2d06a:"7996","556d04db":"8008","5bb3de56":"8012",aa0b35eb:"8176",b5b9c8e0:"8252",e305a15c:"8263","8919ea97":"8372","06d8773d":"8384",a2bed8f0:"8392","8db808e7":"8444",a9946d6a:"8448","0c0efcaa":"8528",a90afd08:"8532",c359af60:"8544",e6b91a21:"8601",c412bf64:"8608","491a3217":"8768","9702a600":"8808",a02168a2:"8858","4fefa35c":"8916","1906a68b":"8928",b065408b:"8934",abc9d724:"8980",e0f83a1d:"9032","62b182e9":"9064","879f7a7c":"9096",d47ba782:"9198",bd8da646:"9258",e436f9fb:"9396","3eb0a99f":"9400",c8131338:"9412","34fbd09a":"9456","1a4e3797":"9648",e9325e77:"9656","293e08e8":"9700","04f8d6af":"9728","1c7a9c9f":"9792",b9f8aa82:"9808"}[e]||e,r.p+r.u(e)},(()=>{var e={296:0,2176:0};r.f.j=(a,f)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)f.push(d[2]);else if(/^2(17|9)6$/.test(a))e[a]=0;else{var b=new Promise(((f,b)=>d=e[a]=[f,b]));f.push(d[2]=b);var c=r.p+r.u(a),t=new Error;r.l(c,(f=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var b=f&&("load"===f.type?"missing":f.type),c=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+b+": "+c+")",t.name="ChunkLoadError",t.type=b,t.request=c,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var d,b,c=f[0],t=f[1],o=f[2],n=0;if(c.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(f);n{"use strict";var e,a,f,d,b={},c={};function r(e){var a=c[e];if(void 0!==a)return a.exports;var f=c[e]={exports:{}};return b[e].call(f.exports,f,f.exports,r),f.exports}r.m=b,e=[],r.O=(a,f,d,b)=>{if(!f){var c=1/0;for(i=0;i=b)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[f,d,b]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var b=Object.create(null);r.r(b);var c={};a=a||[null,f({}),f([]),f(f)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,r.d(b,c),b},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({112:"e44e3f47",172:"21614072",188:"bab022f4",208:"184ad633",264:"3f2a1ecb",379:"9258f162",644:"3c741b47",724:"f5ff54f0",820:"58de4400",904:"3c653e3b",920:"16fe8a4c",956:"cd83de9e",980:"ceca19cd",1008:"1460e89b",1080:"9242256d",1085:"1fdfdeaa",1088:"219c4568",1116:"e2e89445",1200:"bc3f1a98",1240:"e15bcb33",1260:"5c9e12d1",1272:"b4e1da39",1292:"dc4598d0",1352:"0346afaa",1412:"7efbfa7e",1440:"c7401661",1624:"041e4035",1660:"70793eb2",1672:"21a9d6ed",1692:"f8092feb",1728:"d9e16301",1792:"671939c9",1912:"64f1f19c",2008:"9118549b",2012:"af0d8a1e",2068:"00d3276d",2096:"a5a260f1",2124:"c2d67624",2200:"45d37095",2356:"79263788",2416:"6baf1826",2448:"f5711d0d",2632:"c4f5d8e4",2708:"9d4bdb35",2728:"937dc5a6",2756:"3423820d",2760:"420497a2",2762:"413f2abb",2764:"c027c09e",2872:"9a49882e",2900:"be77d225",3016:"def5ef2c",3043:"3caf9b73",3044:"509dc7bf",3048:"99c7964b",3104:"ddb8503b",3116:"bbdc39ec",3128:"12577cfd",3132:"ae565638",3200:"f278ac2c",3280:"e6b9ef91",3292:"fa38ac94",3372:"fa9ab54d",3448:"cbb882cb",3596:"a33b6a74",3600:"e66621bc",3612:"bd470307",3796:"1dbe42a7",3840:"ab17452f",3876:"1db0afb7",4020:"fe661d8a",4072:"495e5e06",4152:"aae2c465",4156:"af0818da",4184:"9d221b96",4217:"6021085e",4220:"a78783ee",4304:"5e95c892",4308:"a373fd77",4440:"f769b3fd",4486:"64cca8ef",4616:"c14a26e3",4666:"a94703ab",4724:"4c2546f9",4824:"6297ff83",4856:"ca86781b",4976:"a6aa9e1f",5008:"5f403532",5048:"c26add1d",5192:"da41ed28",5244:"3eac2097",5336:"1d8647da",5388:"c71502c9",5505:"5a5dcc21",5512:"814f3328",5516:"c8a5dae5",5584:"8a061d83",5680:"acaf655c",5696:"935f2afb",5708:"7d50aa41",5752:"7f661f82",5840:"71a2656f",5868:"c2f60cfc",5920:"eb0c92c1",6040:"7b1f0035",6068:"df12ff2a",6164:"8fdeae25",6180:"25a5a20c",6209:"49bfadd9",6292:"b2b675dd",6322:"15a3954c",6344:"ccc49370",6416:"92185360",6452:"0fe8a02a",6500:"a7bd4aaa",6576:"5bb07cf5",6608:"b784ffba",6680:"f5cfbeab",6714:"4dac5fec",6730:"57bcddd6",6732:"bf6aacca",6748:"bc318449",6752:"17896441",6828:"43455a69",6868:"31868bec",6880:"b2f554cd",6952:"ff0352e3",7012:"56ebd09a",7028:"9e4087bc",7136:"df53045f",7180:"99b7fc87",7192:"3d9729af",7208:"aaff9110",7296:"0ac93784",7332:"c222a988",7552:"a6f42423",7568:"cb9da62d",7664:"62e81aa6",7712:"6d752ef5",7724:"2ba1d2b8",7840:"128c6d36",7848:"07d14bbd",7920:"3c055f5e",7948:"1df9637e",7952:"18328e9e",7996:"acb2d06a",8008:"556d04db",8012:"5bb3de56",8176:"aa0b35eb",8252:"b5b9c8e0",8263:"e305a15c",8372:"8919ea97",8384:"06d8773d",8392:"a2bed8f0",8444:"8db808e7",8448:"a9946d6a",8528:"0c0efcaa",8532:"a90afd08",8544:"c359af60",8601:"e6b91a21",8608:"c412bf64",8768:"491a3217",8808:"9702a600",8858:"a02168a2",8906:"33776668",8916:"4fefa35c",8928:"1906a68b",8934:"b065408b",8980:"abc9d724",9032:"e0f83a1d",9064:"62b182e9",9096:"879f7a7c",9198:"d47ba782",9258:"bd8da646",9396:"e436f9fb",9400:"3eb0a99f",9412:"c8131338",9456:"34fbd09a",9648:"1a4e3797",9656:"e9325e77",9700:"293e08e8",9728:"04f8d6af",9792:"1c7a9c9f",9808:"b9f8aa82"}[e]||e)+"."+{112:"ffbbd5a2",172:"3d6916df",188:"79e4a80e",208:"eea5a87b",264:"fccfb010",379:"0e4d7b0a",606:"027c6754",644:"dd600205",724:"ef4e73e6",820:"0d6348ab",904:"d8e59a5c",920:"68a01e73",956:"1cb8b261",980:"a309122e",1008:"725073a1",1080:"528a43fb",1085:"8a3c90e1",1088:"fc2e112f",1116:"0e7edc0d",1200:"390cae50",1240:"cc1b4e88",1260:"b3bb7e41",1272:"2099fa4d",1292:"6d320dd3",1352:"2a632c4a",1412:"40b6eb7f",1440:"be188dac",1624:"27c01a88",1660:"2305c43d",1672:"fef644e3",1676:"a0d9bd55",1692:"57dc7e74",1728:"32b3bbc5",1792:"7fe26650",1912:"aa3ea31b",2008:"591896b0",2012:"646cf20d",2068:"03674a6d",2096:"f47494d4",2124:"b332c10d",2200:"0ba3ee42",2356:"c00c6910",2416:"2e1ea009",2448:"f7fce5c6",2528:"2436a084",2632:"45587cbf",2708:"132887ba",2728:"7a7e0323",2756:"a542dc61",2760:"e97e3bca",2762:"a3457e4c",2764:"4fc4c65f",2872:"c1ef5e32",2900:"6d04e5db",3016:"240a2ea8",3043:"e8e1a67e",3044:"1f608ccf",3048:"b3616e44",3104:"8d473c1e",3116:"2ba35945",3128:"8dddd7b3",3132:"f2fe2dd6",3200:"124ee451",3280:"f3c9d5af",3292:"73f3b653",3372:"fd1aa6a5",3448:"141e3db8",3596:"2ef6d204",3600:"5479a356",3612:"b8b78b42",3796:"a018a53d",3840:"3d5798e8",3876:"966742a8",4020:"a783da53",4072:"1bf8fe81",4152:"76957a46",4156:"2b0ca4a0",4184:"2ce25209",4217:"454fc3dc",4220:"399d3336",4304:"84883c70",4308:"50ac0805",4440:"6f9bafa0",4486:"47a97907",4552:"a809afa9",4616:"a5d26616",4666:"15af1f33",4724:"aa757dad",4824:"ba2e3f26",4856:"abeae509",4976:"2123d972",5008:"e45b0829",5048:"64a8d6d6",5192:"18b098d4",5244:"20f274f3",5336:"913a6527",5388:"a515464f",5505:"0210552f",5512:"8f5f87e7",5516:"5dadb0ab",5584:"d6beed89",5680:"d93f86b2",5696:"f9b2dd0c",5708:"76d6ebf0",5752:"36188801",5840:"d89b2af4",5868:"c2fd70a8",5920:"08bdd6e6",6040:"f46eb7ff",6068:"2ada05aa",6164:"4cf4e160",6180:"58d19b0c",6209:"8ce1a55c",6292:"1a619e45",6322:"da84e45e",6344:"79bdc319",6416:"62040dd7",6452:"9a882eef",6500:"ad11e11e",6576:"2d190a20",6608:"157cb050",6680:"8aceb2e0",6714:"4d9bde8d",6730:"5a4351c7",6732:"52379e0a",6748:"0acbe71c",6752:"ff15626b",6828:"ef40ff61",6868:"a2757938",6880:"bf75ef81",6952:"452e946b",7012:"8d1bf24f",7028:"e5742792",7136:"d1effc72",7180:"fd1ec705",7192:"f3228e08",7208:"8ee7db0a",7296:"141b2ea4",7332:"c8e180b7",7552:"45269320",7568:"c7d307bc",7664:"0d34f5ce",7712:"08611302",7724:"ddfb9119",7840:"6a105ea1",7848:"cb4af53a",7920:"104ed9fb",7948:"c9dfcd9d",7952:"d67c2c99",7996:"3da611ed",8008:"faf8a5ff",8012:"5e6c7cc5",8176:"f5d90ee0",8252:"f9249c3a",8263:"bd5a9ce2",8372:"9362dd44",8384:"b5758238",8392:"31624d4e",8444:"92e5af8b",8448:"081419be",8528:"993152bb",8532:"25cd3588",8544:"c62dc728",8601:"8a291491",8608:"b0e14a54",8768:"0ca8966a",8808:"1e2ebe76",8858:"dd051560",8879:"fbade3c5",8906:"599a6778",8916:"39c80c62",8928:"2a1eef90",8934:"2540184c",8980:"7b4df509",9032:"b75166be",9064:"de7ab418",9096:"312e269b",9116:"f0ae5377",9198:"b0e2468a",9258:"1266cf6c",9396:"644a2877",9400:"91186561",9412:"ca0da140",9456:"3daf123e",9648:"67f3f595",9656:"166166de",9700:"7411a2d9",9728:"1acbacea",9792:"a953a687",9808:"cc78e901"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},r.l=(e,a,f,b)=>{if(d[e])d[e].push(a);else{var c,t;if(void 0!==f)for(var o=document.getElementsByTagName("script"),n=0;n{c.onerror=c.onload=null,clearTimeout(l);var b=d[e];if(delete d[e],c.parentNode&&c.parentNode.removeChild(c),b&&b.forEach((e=>e(f))),a)return a(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:c}),12e4);c.onerror=u.bind(null,c.onerror),c.onload=u.bind(null,c.onload),t&&document.head.appendChild(c)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"6752",21614072:"172",33776668:"8906",79263788:"2356",92185360:"6416",e44e3f47:"112",bab022f4:"188","184ad633":"208","3f2a1ecb":"264","9258f162":"379","3c741b47":"644",f5ff54f0:"724","58de4400":"820","3c653e3b":"904","16fe8a4c":"920",cd83de9e:"956",ceca19cd:"980","1460e89b":"1008","9242256d":"1080","1fdfdeaa":"1085","219c4568":"1088",e2e89445:"1116",bc3f1a98:"1200",e15bcb33:"1240","5c9e12d1":"1260",b4e1da39:"1272",dc4598d0:"1292","0346afaa":"1352","7efbfa7e":"1412",c7401661:"1440","041e4035":"1624","70793eb2":"1660","21a9d6ed":"1672",f8092feb:"1692",d9e16301:"1728","671939c9":"1792","64f1f19c":"1912","9118549b":"2008",af0d8a1e:"2012","00d3276d":"2068",a5a260f1:"2096",c2d67624:"2124","45d37095":"2200","6baf1826":"2416",f5711d0d:"2448",c4f5d8e4:"2632","9d4bdb35":"2708","937dc5a6":"2728","3423820d":"2756","420497a2":"2760","413f2abb":"2762",c027c09e:"2764","9a49882e":"2872",be77d225:"2900",def5ef2c:"3016","3caf9b73":"3043","509dc7bf":"3044","99c7964b":"3048",ddb8503b:"3104",bbdc39ec:"3116","12577cfd":"3128",ae565638:"3132",f278ac2c:"3200",e6b9ef91:"3280",fa38ac94:"3292",fa9ab54d:"3372",cbb882cb:"3448",a33b6a74:"3596",e66621bc:"3600",bd470307:"3612","1dbe42a7":"3796",ab17452f:"3840","1db0afb7":"3876",fe661d8a:"4020","495e5e06":"4072",aae2c465:"4152",af0818da:"4156","9d221b96":"4184","6021085e":"4217",a78783ee:"4220","5e95c892":"4304",a373fd77:"4308",f769b3fd:"4440","64cca8ef":"4486",c14a26e3:"4616",a94703ab:"4666","4c2546f9":"4724","6297ff83":"4824",ca86781b:"4856",a6aa9e1f:"4976","5f403532":"5008",c26add1d:"5048",da41ed28:"5192","3eac2097":"5244","1d8647da":"5336",c71502c9:"5388","5a5dcc21":"5505","814f3328":"5512",c8a5dae5:"5516","8a061d83":"5584",acaf655c:"5680","935f2afb":"5696","7d50aa41":"5708","7f661f82":"5752","71a2656f":"5840",c2f60cfc:"5868",eb0c92c1:"5920","7b1f0035":"6040",df12ff2a:"6068","8fdeae25":"6164","25a5a20c":"6180","49bfadd9":"6209",b2b675dd:"6292","15a3954c":"6322",ccc49370:"6344","0fe8a02a":"6452",a7bd4aaa:"6500","5bb07cf5":"6576",b784ffba:"6608",f5cfbeab:"6680","4dac5fec":"6714","57bcddd6":"6730",bf6aacca:"6732",bc318449:"6748","43455a69":"6828","31868bec":"6868",b2f554cd:"6880",ff0352e3:"6952","56ebd09a":"7012","9e4087bc":"7028",df53045f:"7136","99b7fc87":"7180","3d9729af":"7192",aaff9110:"7208","0ac93784":"7296",c222a988:"7332",a6f42423:"7552",cb9da62d:"7568","62e81aa6":"7664","6d752ef5":"7712","2ba1d2b8":"7724","128c6d36":"7840","07d14bbd":"7848","3c055f5e":"7920","1df9637e":"7948","18328e9e":"7952",acb2d06a:"7996","556d04db":"8008","5bb3de56":"8012",aa0b35eb:"8176",b5b9c8e0:"8252",e305a15c:"8263","8919ea97":"8372","06d8773d":"8384",a2bed8f0:"8392","8db808e7":"8444",a9946d6a:"8448","0c0efcaa":"8528",a90afd08:"8532",c359af60:"8544",e6b91a21:"8601",c412bf64:"8608","491a3217":"8768","9702a600":"8808",a02168a2:"8858","4fefa35c":"8916","1906a68b":"8928",b065408b:"8934",abc9d724:"8980",e0f83a1d:"9032","62b182e9":"9064","879f7a7c":"9096",d47ba782:"9198",bd8da646:"9258",e436f9fb:"9396","3eb0a99f":"9400",c8131338:"9412","34fbd09a":"9456","1a4e3797":"9648",e9325e77:"9656","293e08e8":"9700","04f8d6af":"9728","1c7a9c9f":"9792",b9f8aa82:"9808"}[e]||e,r.p+r.u(e)},(()=>{var e={296:0,2176:0};r.f.j=(a,f)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)f.push(d[2]);else if(/^2(17|9)6$/.test(a))e[a]=0;else{var b=new Promise(((f,b)=>d=e[a]=[f,b]));f.push(d[2]=b);var c=r.p+r.u(a),t=new Error;r.l(c,(f=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var b=f&&("load"===f.type?"missing":f.type),c=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+b+": "+c+")",t.name="ChunkLoadError",t.type=b,t.request=c,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var d,b,c=f[0],t=f[1],o=f[2],n=0;if(c.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(f);n

PULSE_DICT_MISSING_KEY

+

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'];
}

PULSE_READONLY_SHARED_PTR_PARAM

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.

@@ -1351,6 +1359,6 @@

Replace 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.

+we assume that any captured weak pointer whose name contains "self" is a weak reference to self.

\ No newline at end of file diff --git a/docs/next/analyzing-apps-or-projects/index.html b/docs/next/analyzing-apps-or-projects/index.html index ebd7319b917..308111703c9 100644 --- a/docs/next/analyzing-apps-or-projects/index.html +++ b/docs/next/analyzing-apps-or-projects/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-annotation-reachability/index.html b/docs/next/checker-annotation-reachability/index.html index 99982216468..695ca009093 100644 --- a/docs/next/checker-annotation-reachability/index.html +++ b/docs/next/checker-annotation-reachability/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-biabduction/index.html b/docs/next/checker-biabduction/index.html index 008f18c9306..61830cd53a9 100644 --- a/docs/next/checker-biabduction/index.html +++ b/docs/next/checker-biabduction/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-bufferoverrun/index.html b/docs/next/checker-bufferoverrun/index.html index 183c5cf036f..6c0eefa0205 100644 --- a/docs/next/checker-bufferoverrun/index.html +++ b/docs/next/checker-bufferoverrun/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-config-impact-analysis/index.html b/docs/next/checker-config-impact-analysis/index.html index 109e40ad477..9a00c927ecd 100644 --- a/docs/next/checker-config-impact-analysis/index.html +++ b/docs/next/checker-config-impact-analysis/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-cost/index.html b/docs/next/checker-cost/index.html index 1188dba29c8..8c6264385df 100644 --- a/docs/next/checker-cost/index.html +++ b/docs/next/checker-cost/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-datalog/index.html b/docs/next/checker-datalog/index.html index d5efedc2a90..e4500999c15 100644 --- a/docs/next/checker-datalog/index.html +++ b/docs/next/checker-datalog/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-fragment-retains-view/index.html b/docs/next/checker-fragment-retains-view/index.html index 11d508c5975..841773f85e0 100644 --- a/docs/next/checker-fragment-retains-view/index.html +++ b/docs/next/checker-fragment-retains-view/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-impurity/index.html b/docs/next/checker-impurity/index.html index cd2dc61d01e..2b2659142c0 100644 --- a/docs/next/checker-impurity/index.html +++ b/docs/next/checker-impurity/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-inefficient-keyset-iterator/index.html b/docs/next/checker-inefficient-keyset-iterator/index.html index 93436ee7875..20ccd7e2adf 100644 --- a/docs/next/checker-inefficient-keyset-iterator/index.html +++ b/docs/next/checker-inefficient-keyset-iterator/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-lineage/index.html b/docs/next/checker-lineage/index.html index 32af24e9be1..13d6274f71d 100644 --- a/docs/next/checker-lineage/index.html +++ b/docs/next/checker-lineage/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-litho-required-props/index.html b/docs/next/checker-litho-required-props/index.html index 182c1435d47..30fd93d4f01 100644 --- a/docs/next/checker-litho-required-props/index.html +++ b/docs/next/checker-litho-required-props/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-liveness/index.html b/docs/next/checker-liveness/index.html index 2a46ec48147..fa1e34816c5 100644 --- a/docs/next/checker-liveness/index.html +++ b/docs/next/checker-liveness/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-loop-hoisting/index.html b/docs/next/checker-loop-hoisting/index.html index 4915153959b..ba4d4f68037 100644 --- a/docs/next/checker-loop-hoisting/index.html +++ b/docs/next/checker-loop-hoisting/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-parameter-not-null-checked/index.html b/docs/next/checker-parameter-not-null-checked/index.html index afe47a91772..f39776575d7 100644 --- a/docs/next/checker-parameter-not-null-checked/index.html +++ b/docs/next/checker-parameter-not-null-checked/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-printf-args/index.html b/docs/next/checker-printf-args/index.html index 48a3068a15f..c5ababeda75 100644 --- a/docs/next/checker-printf-args/index.html +++ b/docs/next/checker-printf-args/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-pulse/index.html b/docs/next/checker-pulse/index.html index fc8834ea484..20d2b67f42a 100644 --- a/docs/next/checker-pulse/index.html +++ b/docs/next/checker-pulse/index.html @@ -13,7 +13,7 @@ - + @@ -24,7 +24,7 @@
  • C/C++/ObjC: Yes
  • C#/.Net: No
  • Erlang: Experimental
  • -
  • Hack: No
  • +
  • Hack: Yes
  • Java: Yes
  • Python: No
  • @@ -90,6 +90,7 @@

    List of
  • OPTIONAL_EMPTY_ACCESS
  • OPTIONAL_EMPTY_ACCESS_LATENT
  • PULSE_CONST_REFABLE
  • +
  • PULSE_DICT_MISSING_KEY
  • PULSE_READONLY_SHARED_PTR_PARAM
  • PULSE_REFERENCE_STABILITY
  • PULSE_RESOURCE_LEAK
  • diff --git a/docs/next/checker-purity/index.html b/docs/next/checker-purity/index.html index ba090832ec4..f9b5a5d82e9 100644 --- a/docs/next/checker-purity/index.html +++ b/docs/next/checker-purity/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-quandary/index.html b/docs/next/checker-quandary/index.html index 927bafafa34..ee785d69fee 100644 --- a/docs/next/checker-quandary/index.html +++ b/docs/next/checker-quandary/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-racerd/index.html b/docs/next/checker-racerd/index.html index dd6f61f6cb2..b4f8a398352 100644 --- a/docs/next/checker-racerd/index.html +++ b/docs/next/checker-racerd/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-resource-leak-lab/index.html b/docs/next/checker-resource-leak-lab/index.html index c8e607ecc66..cf8aef7747e 100644 --- a/docs/next/checker-resource-leak-lab/index.html +++ b/docs/next/checker-resource-leak-lab/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-scope-leakage/index.html b/docs/next/checker-scope-leakage/index.html index bacf7442ced..421da6a8c44 100644 --- a/docs/next/checker-scope-leakage/index.html +++ b/docs/next/checker-scope-leakage/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-self-in-block/index.html b/docs/next/checker-self-in-block/index.html index b46c9e9f306..46b35a77cba 100644 --- a/docs/next/checker-self-in-block/index.html +++ b/docs/next/checker-self-in-block/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-sil-validation/index.html b/docs/next/checker-sil-validation/index.html index 43770967209..48a19ce91aa 100644 --- a/docs/next/checker-sil-validation/index.html +++ b/docs/next/checker-sil-validation/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-siof/index.html b/docs/next/checker-siof/index.html index 0214765a089..2712348bde8 100644 --- a/docs/next/checker-siof/index.html +++ b/docs/next/checker-siof/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-starvation/index.html b/docs/next/checker-starvation/index.html index 2bf80d66b03..228b319f8ca 100644 --- a/docs/next/checker-starvation/index.html +++ b/docs/next/checker-starvation/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-topl/index.html b/docs/next/checker-topl/index.html index feb77b1c6c1..a767427e416 100644 --- a/docs/next/checker-topl/index.html +++ b/docs/next/checker-topl/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/checker-uninit/index.html b/docs/next/checker-uninit/index.html index 80cf465adff..cfe57519f63 100644 --- a/docs/next/checker-uninit/index.html +++ b/docs/next/checker-uninit/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/getting-started/index.html b/docs/next/getting-started/index.html index 1caecc7565f..8909f92a96d 100644 --- a/docs/next/getting-started/index.html +++ b/docs/next/getting-started/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/hello-world/index.html b/docs/next/hello-world/index.html index 6c51bff37f5..7042ad04922 100644 --- a/docs/next/hello-world/index.html +++ b/docs/next/hello-world/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/infer-workflow/index.html b/docs/next/infer-workflow/index.html index 5272441fe80..e416d43866e 100644 --- a/docs/next/infer-workflow/index.html +++ b/docs/next/infer-workflow/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/internal-API/index.html b/docs/next/internal-API/index.html index e664fa54ff1..3296597ad97 100644 --- a/docs/next/internal-API/index.html +++ b/docs/next/internal-API/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-analyze/index.html b/docs/next/man-infer-analyze/index.html index 15037c05c65..6fce5faeb8d 100644 --- a/docs/next/man-infer-analyze/index.html +++ b/docs/next/man-infer-analyze/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-capture/index.html b/docs/next/man-infer-capture/index.html index bf2f5306744..2de5a815b6f 100644 --- a/docs/next/man-infer-capture/index.html +++ b/docs/next/man-infer-capture/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-compile/index.html b/docs/next/man-infer-compile/index.html index a3b486a5dad..1c021e7f1b0 100644 --- a/docs/next/man-infer-compile/index.html +++ b/docs/next/man-infer-compile/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-debug/index.html b/docs/next/man-infer-debug/index.html index e2299d379af..9bb72931495 100644 --- a/docs/next/man-infer-debug/index.html +++ b/docs/next/man-infer-debug/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-explore/index.html b/docs/next/man-infer-explore/index.html index 4779815eabc..7e2d1b5749d 100644 --- a/docs/next/man-infer-explore/index.html +++ b/docs/next/man-infer-explore/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-help/index.html b/docs/next/man-infer-help/index.html index a953de81369..80f1d4ba9b3 100644 --- a/docs/next/man-infer-help/index.html +++ b/docs/next/man-infer-help/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-report/index.html b/docs/next/man-infer-report/index.html index e49b77f77af..a3e78da06ff 100644 --- a/docs/next/man-infer-report/index.html +++ b/docs/next/man-infer-report/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-reportdiff/index.html b/docs/next/man-infer-reportdiff/index.html index b22e5bda729..53f493e393a 100644 --- a/docs/next/man-infer-reportdiff/index.html +++ b/docs/next/man-infer-reportdiff/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer-run/index.html b/docs/next/man-infer-run/index.html index 8e4399bbc1c..984be3c8826 100644 --- a/docs/next/man-infer-run/index.html +++ b/docs/next/man-infer-run/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-infer/index.html b/docs/next/man-infer/index.html index 91b8c3a80d1..dbe493c6a75 100644 --- a/docs/next/man-infer/index.html +++ b/docs/next/man-infer/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/man-pages/index.html b/docs/next/man-pages/index.html index b6a403eb638..a6657175a2d 100644 --- a/docs/next/man-pages/index.html +++ b/docs/next/man-pages/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/separation-logic-and-bi-abduction/index.html b/docs/next/separation-logic-and-bi-abduction/index.html index 30be16d0c9b..66230e3ea4b 100644 --- a/docs/next/separation-logic-and-bi-abduction/index.html +++ b/docs/next/separation-logic-and-bi-abduction/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/steps-for-ci/index.html b/docs/next/steps-for-ci/index.html index f16c98c30c8..aa8cf3b2c3e 100644 --- a/docs/next/steps-for-ci/index.html +++ b/docs/next/steps-for-ci/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/support/index.html b/docs/next/support/index.html index bd69561d894..2a8ca913eb8 100644 --- a/docs/next/support/index.html +++ b/docs/next/support/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/next/versions/index.html b/docs/next/versions/index.html index 5ba29941d0d..5983a25127a 100644 --- a/docs/next/versions/index.html +++ b/docs/next/versions/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/separation-logic-and-bi-abduction/index.html b/docs/separation-logic-and-bi-abduction/index.html index 78e9cf41ac4..17445cff7e6 100644 --- a/docs/separation-logic-and-bi-abduction/index.html +++ b/docs/separation-logic-and-bi-abduction/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/steps-for-ci/index.html b/docs/steps-for-ci/index.html index aab06dfddbc..f6b45c7ff5b 100644 --- a/docs/steps-for-ci/index.html +++ b/docs/steps-for-ci/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/support/index.html b/docs/support/index.html index 47ffe46b7ff..9e4e04b2462 100644 --- a/docs/support/index.html +++ b/docs/support/index.html @@ -13,7 +13,7 @@ - + diff --git a/docs/versions/index.html b/docs/versions/index.html index 25cc77df612..f85d4852b7c 100644 --- a/docs/versions/index.html +++ b/docs/versions/index.html @@ -13,7 +13,7 @@ - + diff --git a/index.html b/index.html index 731510fe9d5..270ab494363 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,7 @@ - + diff --git a/man/next/infer-analyze.1.html b/man/next/infer-analyze.1.html index bb324b61f8f..7037b222443 100644 --- a/man/next/infer-analyze.1.html +++ b/man/next/infer-analyze.1.html @@ -1066,16 +1066,34 @@

    JAVA OPTIONS

    --annotation-reachability-custom-pairs json

    -

    Specify custom sources/sink for -the annotation reachability checker

    +

    Specify custom sources/sinks +for the annotation reachability checker

    Example format: for custom annotations
    com.my.annotation.{Source1,Source2,Sink1}
    { "sources" : ["Source1", -"Source2"], "sink" : "Sink1" } -
    ---external-java-packages
    +prefix

    +"Source2"], "sinks" : +["Sink1"] }
    +--annotation-reachability-expensive

    + +

    Activates: check if expensive +methods (annotated @Expensive or modeled) can call +@PerformanceCritical (with annotation reachability checker) +(Conversely: +--no-annotation-reachability-expensive)

    + + +

    --annotation-reachability-no-allocation

    + +

    Activates: check if methods +annotated with @NoAllocation can allocate (with annotation +reachability checker) (Conversely: +--no-annotation-reachability-no-allocation)

    + + +

    --external-java-packages ++prefix

    Specify a list of Java package prefixes for external Java packages. If set, the analysis diff --git a/man/next/infer-report.1.html b/man/next/infer-report.1.html index bf4c17ed8b6..52429b1988d 100644 --- a/man/next/infer-report.1.html +++ b/man/next/infer-report.1.html @@ -334,6 +334,7 @@

    OPTIONS PREMATURE_NIL_TERMINATION_ARGUMENT (enabled by default),
    PULSE_CONST_REFABLE (enabled by default),
    +PULSE_DICT_MISSING_KEY (disabled by default),
    PULSE_READONLY_SHARED_PTR_PARAM (enabled by default),
    PULSE_REFERENCE_STABILITY (disabled by default),
    PULSE_RESOURCE_LEAK (enabled by default),
    @@ -361,7 +362,7 @@

    OPTIONS QUANDARY_TAINT_ERROR (enabled by default),
    REGEX_OP_ON_UI_THREAD (enabled by default),
    RESOURCE_LEAK (enabled by default),
    -RETAIN_CYCLE (disabled by default),
    +RETAIN_CYCLE (enabled by default),
    SCOPE_LEAKAGE (enabled by default),
    SENSITIVE_DATA_FLOW (disabled by default),
    SHELL_INJECTION (enabled by default),
    diff --git a/man/next/infer.1.html b/man/next/infer.1.html index 4d262edf0f4..8f00eb2e6f0 100644 --- a/man/next/infer.1.html +++ b/man/next/infer.1.html @@ -142,15 +142,15 @@

    OPTIONS infer-analyze(1).
    --annotation-reachability-custom-pairs
    json

    -

    Specify custom sources/sink for -the annotation reachability checker

    +

    Specify custom sources/sinks +for the annotation reachability checker

    Example format: for custom annotations
    com.my.annotation.{Source1,Source2,Sink1}
    { "sources" : ["Source1", -"Source2"], "sink" : "Sink1" } -
    +"Source2"], "sinks" : +["Sink1"] }
    See also infer-analyze(1).
    --annotation-reachability-cxx
    json

    @@ -192,6 +192,25 @@

    OPTIONS annotation reachability specs with the given sources spec

    +

    See also +infer-analyze(1).
    +--annotation-reachability-expensive

    + +

    Activates: check if expensive +methods (annotated @Expensive or modeled) can call +@PerformanceCritical (with annotation reachability checker) +(Conversely: +--no-annotation-reachability-expensive)

    + +

    See also +infer-analyze(1).
    +--annotation-reachability-no-allocation

    + +

    Activates: check if methods +annotated with @NoAllocation can allocate (with annotation +reachability checker) (Conversely: +--no-annotation-reachability-no-allocation)

    +

    See also infer-analyze(1).
    --annotation-reachability-only

    @@ -1011,6 +1030,7 @@

    OPTIONS PREMATURE_NIL_TERMINATION_ARGUMENT (enabled by default),
    PULSE_CONST_REFABLE (enabled by default),
    +PULSE_DICT_MISSING_KEY (disabled by default),
    PULSE_READONLY_SHARED_PTR_PARAM (enabled by default),
    PULSE_REFERENCE_STABILITY (disabled by default),
    PULSE_RESOURCE_LEAK (enabled by default),
    @@ -1038,7 +1058,7 @@

    OPTIONS QUANDARY_TAINT_ERROR (enabled by default),
    REGEX_OP_ON_UI_THREAD (enabled by default),
    RESOURCE_LEAK (enabled by default),
    -RETAIN_CYCLE (disabled by default),
    +RETAIN_CYCLE (enabled by default),
    SCOPE_LEAKAGE (enabled by default),
    SENSITIVE_DATA_FLOW (disabled by default),
    SHELL_INJECTION (enabled by default),
    diff --git a/odoc/next/infer/Absint/Annotations/index.html b/odoc/next/infer/Absint/Annotations/index.html index 3bbc626fee3..b896e9490fd 100644 --- a/odoc/next/infer/Absint/Annotations/index.html +++ b/odoc/next/infer/Absint/Annotations/index.html @@ -1,5 +1,5 @@ -Annotations (infer.Absint.Annotations)

    Module Absint.Annotations

    Annotations.

    val any_thread : string
    val auto_cleanup : string
    val expensive : string
    val inject_prop : string
    val immutable : string
    val lockless : string
    val no_allocation : string
    val nullable : string
    val nonnull : string
    val performance_critical : string
    val prop : string
    val for_non_ui_thread : string
    val for_ui_thread : string
    val guarded_by : string
    val suppress_lint : string
    val thread_safe : string
    val mainthread : string
    val ui_thread : string
    val worker_thread : string
    val visibleForTesting : string
    val annot_ends_with : IR.Annot.t -> string -> bool

    annot_ends_with annot ann_name returns true if the class name of annot, without the package, is equal to ann_name

    val ia_ends_with : IR.Annot.Item.t -> string -> bool

    Check if there is an annotation in ia which ends with the given name

    val ia_has_annotation_with : IR.Annot.Item.t -> (IR.Annot.t -> bool) -> bool
    val ia_is_initializer : IR.Annot.Item.t -> bool
    val ia_is_nonnull : IR.Annot.Item.t -> bool
    val ia_is_jetbrains_notnull : IR.Annot.Item.t -> bool
    val ia_is_nullable : IR.Annot.Item.t -> bool
    val ia_is_nullsafe_strict : IR.Annot.Item.t -> bool
    val ia_find_nullsafe : IR.Annot.Item.t -> IR.Annot.t option
    val ia_is_expensive : IR.Annot.Item.t -> bool
    val ia_is_functional : IR.Annot.Item.t -> bool
    val ia_is_ignore_allocations : IR.Annot.Item.t -> bool
    val ia_is_inject : IR.Annot.Item.t -> bool
    val ia_is_suppress_lint : IR.Annot.Item.t -> bool
    val ia_is_not_thread_safe : IR.Annot.Item.t -> bool
    val ia_is_nonblocking : IR.Annot.Item.t -> bool
    val ia_is_returns_ownership : IR.Annot.Item.t -> bool
    val ia_is_synchronized_collection : IR.Annot.Item.t -> bool
    val ia_is_thread_safe : IR.Annot.Item.t -> bool
    val ia_is_thread_confined : IR.Annot.Item.t -> bool
    val ia_is_thrift_service : IR.Annot.Item.t -> bool
    val ia_is_volatile : IR.Annot.Item.t -> bool
    val ia_is_worker_thread : IR.Annot.Item.t -> bool
    val ia_is_uithread_equivalent : IR.Annot.Item.t -> bool
    val pdesc_has_return_annot : IR.Procdesc.t -> (IR.Annot.Item.t -> bool) -> bool

    return true if the given predicate evaluates to true on the annotation of pdesc's return value

    val pname_has_return_annot : IR.Procname.t -> (IR.Annot.Item.t -> bool) -> bool

    return true if the given predicate evaluates to true on the annotation of pname's return value

    val attrs_return_annot_ends_with : IR.ProcAttributes.t -> string -> bool

    return true if return value in attrs is annotated with a value ending with the given string

    val method_has_annotation_with : +Annotations (infer.Absint.Annotations)

    Module Absint.Annotations

    Annotations.

    val auto_cleanup : string
    val expensive : string
    val inject_prop : string
    val immutable : string
    val lockless : string
    val no_allocation : string
    val nullable : string
    val nonnull : string
    val performance_critical : string
    val prop : string
    val for_non_ui_thread : string
    val for_ui_thread : string
    val guarded_by : string
    val suppress_lint : string
    val thread_safe : string
    val visibleForTesting : string
    val annot_ends_with : IR.Annot.t -> string -> bool

    annot_ends_with annot ann_name returns true if the class name of annot, without the package, is equal to ann_name

    val ia_ends_with : IR.Annot.Item.t -> string -> bool

    Check if there is an annotation in ia which ends with the given name

    val ia_has_annotation_with : IR.Annot.Item.t -> (IR.Annot.t -> bool) -> bool
    val ia_is_initializer : IR.Annot.Item.t -> bool
    val ia_is_nonnull : IR.Annot.Item.t -> bool
    val ia_is_jetbrains_notnull : IR.Annot.Item.t -> bool
    val ia_is_nullable : IR.Annot.Item.t -> bool
    val ia_is_nullsafe_strict : IR.Annot.Item.t -> bool
    val ia_find_nullsafe : IR.Annot.Item.t -> IR.Annot.t option
    val ia_is_expensive : IR.Annot.Item.t -> bool
    val ia_is_functional : IR.Annot.Item.t -> bool
    val ia_is_ignore_allocations : IR.Annot.Item.t -> bool
    val ia_is_inject : IR.Annot.Item.t -> bool
    val ia_is_suppress_lint : IR.Annot.Item.t -> bool
    val ia_is_not_thread_safe : IR.Annot.Item.t -> bool
    val ia_is_nonblocking : IR.Annot.Item.t -> bool
    val ia_is_returns_ownership : IR.Annot.Item.t -> bool
    val ia_is_synchronized_collection : IR.Annot.Item.t -> bool
    val ia_is_thread_safe : IR.Annot.Item.t -> bool
    val ia_is_thread_confined : IR.Annot.Item.t -> bool
    val ia_is_thrift_service : IR.Annot.Item.t -> bool
    val ia_is_volatile : IR.Annot.Item.t -> bool
    val ia_is_worker_thread : IR.Annot.Item.t -> bool
    val ia_is_uithread_equivalent : IR.Annot.Item.t -> bool
    val pdesc_has_return_annot : IR.Procdesc.t -> (IR.Annot.Item.t -> bool) -> bool

    return true if the given predicate evaluates to true on the annotation of pdesc's return value

    val pname_has_return_annot : IR.Procname.t -> (IR.Annot.Item.t -> bool) -> bool

    return true if the given predicate evaluates to true on the annotation of pname's return value

    val attrs_return_annot_ends_with : IR.ProcAttributes.t -> string -> bool

    return true if return value in attrs is annotated with a value ending with the given string

    val method_has_annotation_with : IR.Annot.Item.t -> IR.Annot.Item.t list -> (IR.Annot.t -> bool) -> diff --git a/odoc/next/infer/Absint/PatternMatch/index.html b/odoc/next/infer/Absint/PatternMatch/index.html index 42adedc9d54..f808f9ef92b 100644 --- a/odoc/next/infer/Absint/PatternMatch/index.html +++ b/odoc/next/infer/Absint/PatternMatch/index.html @@ -25,6 +25,6 @@ unit

    Apply the given predicate to procname and each override of procname. For the moment, this only works for Java

    val type_name_get_annotation : IR.Tenv.t -> IR.Typ.name -> - IR.Annot.Item.t option
    val type_get_annotation : IR.Tenv.t -> IR.Typ.t -> IR.Annot.Item.t option
    val type_is_class : IR.Typ.t -> bool

    Is the type a class type

    val get_fields_nullified : IR.Procdesc.t -> IR.Fieldname.Set.t

    return the set of instance fields that are assigned to a null literal in procdesc

    val has_same_signature : + IR.Annot.Item.t option
    val type_get_annotation : IR.Tenv.t -> IR.Typ.t -> IR.Annot.Item.t option
    val type_is_class : IR.Typ.t -> bool

    Is the type a class type

    val get_fields_nullified : IR.Procdesc.t -> IR.Fieldname.Set.t

    return the set of instance fields that are assigned to a null literal in procdesc

    val has_same_signature : IR.Procname.t -> (IR.Procname.t -> bool) IStdlib.IStd.Staged.t

    For a given procname checks if the method has the same method name, number, order and types of parameters.)

    module ObjectiveC : sig ... end
    val is_entry_point : IR.Procname.t -> bool

    Does the function name correspond to a known entry point? Currently only matches "main"

    \ No newline at end of file diff --git a/odoc/next/infer/Absint/ProcnameDispatcher/Call/index.html b/odoc/next/infer/Absint/ProcnameDispatcher/Call/index.html index 0d98cb8a253..f17fe7060a0 100644 --- a/odoc/next/infer/Absint/ProcnameDispatcher/Call/index.html +++ b/odoc/next/infer/Absint/ProcnameDispatcher/Call/index.html @@ -129,6 +129,9 @@ ('context, 'f_in, _, 'arg_payload FuncArg.t list -> 'f_out, 'arg_payload) args_matcher -> 'f_in -> + ('context, 'f_out, 'arg_payload) matcher

    Ends and captures ALL function arguments as a list and binds the function

    val ($+++$-->) : + ('context, 'f_in, _, 'arg_payload list -> 'f_out, 'arg_payload) args_matcher -> + 'f_in -> ('context, 'f_out, 'arg_payload) matcher

    Ends and captures ALL function arguments as a list and binds the function

    val (>$$-->) : ('context, 'f_in, 'f_out, _, 'arg_payload) templ_matcher -> 'f_in -> @@ -155,6 +158,9 @@ ('context, 'f_in, 'arg_payload FuncArg.t list -> 'f_out, 'arg_payload) name_matcher -> 'f_in -> + ('context, 'f_out, 'arg_payload) matcher

    After a name, accepts ALL template arguments, accepts ALL path tails (names, templates), captures ALL function arguments as a list, binds the function

    val (&::.*+++>) : + ('context, 'f_in, 'arg_payload list -> 'f_out, 'arg_payload) name_matcher -> + 'f_in -> ('context, 'f_out, 'arg_payload) matcher

    After a name, accepts ALL template arguments, accepts ALL path tails (names, templates), captures ALL function arguments as a list, binds the function

    val ($!-->) : ('context, 'f_in, 'f_proc_out, 'f_out, 'arg_payload) args_matcher -> 'f_in -> diff --git a/odoc/next/infer/Backend/CallGraphScheduler/index.html b/odoc/next/infer/Backend/CallGraphScheduler/index.html index 7494396a878..526a37dbb11 100644 --- a/odoc/next/infer/Backend/CallGraphScheduler/index.html +++ b/odoc/next/infer/Backend/CallGraphScheduler/index.html @@ -1,4 +1,4 @@ CallGraphScheduler (infer.Backend.CallGraphScheduler)

    Module Backend.CallGraphScheduler

    \ No newline at end of file + (Absint.TaskSchedulerTypes.target, 'a) IBase.ProcessPool.TaskGenerator.t
    \ No newline at end of file diff --git a/odoc/next/infer/Backend/CallbackOfChecker/index.html b/odoc/next/infer/Backend/CallbackOfChecker/index.html index 3bdeb91ddb5..cc8bdc5f251 100644 --- a/odoc/next/infer/Backend/CallbackOfChecker/index.html +++ b/odoc/next/infer/Backend/CallbackOfChecker/index.html @@ -25,11 +25,12 @@ Summary.t -> bool
    val interprocedural_with_field_dependency : dep_field:(Payloads.t, 'payload_dep IStdlib.IStd.Lazy.t) IStdlib.IStd.Field.t -> - (Payloads.t, 'payload option IStdlib.IStd.Lazy.t) IStdlib.IStd.Field.t -> - ('payload Absint.InterproceduralAnalysis.t -> + (Payloads.t, 'payload IStdlib.IStd.Lazy.t) IStdlib.IStd.Field.t -> + (('payload * 'payload_dep) Absint.InterproceduralAnalysis.t -> 'payload_dep -> - 'payload option) -> - Callbacks.proc_callback_t

    An inter-procedural analysis that depends on the summary payload found by another one for a procedure to analyse the same procedure.

    val interprocedural_file : + 'payload) -> + Callbacks.proc_callback_args -> + Summary.t

    An inter-procedural analysis that depends on the summary payload found by another one for a procedure to analyse the same procedure. The checker will be passed that payload dependency as an argument for the procedure being analysed. The InterproceduralAnalysis argument allows retrieving both the dependency payload and the "current" one on other procedures.

    val interprocedural_file : (Payloads.t, 'payload option IStdlib.IStd.Lazy.t) IStdlib.IStd.Field.t -> ('payload Absint.InterproceduralAnalysis.file_t -> Absint.IssueLog.t) -> Callbacks.file_callback_t

    interprocedural_file field checker expects checker to compute an Absint.IssueLog.t from the file-level analysis, given an inter-procedural analysis of dependencies that computes the payload type corresponding to field

    val intraprocedural : diff --git a/odoc/next/infer/Backend/FileScheduler/index.html b/odoc/next/infer/Backend/FileScheduler/index.html index e0fa4bd0b12..2e9e44d9f16 100644 --- a/odoc/next/infer/Backend/FileScheduler/index.html +++ b/odoc/next/infer/Backend/FileScheduler/index.html @@ -1,4 +1,4 @@ FileScheduler (infer.Backend.FileScheduler)

    Module Backend.FileScheduler

    \ No newline at end of file + (Absint.TaskSchedulerTypes.target, 'a) IBase.ProcessPool.TaskGenerator.t
    \ No newline at end of file diff --git a/odoc/next/infer/Backend/ReplayScheduler/index.html b/odoc/next/infer/Backend/ReplayScheduler/index.html index a12c4746c26..66e336e62d7 100644 --- a/odoc/next/infer/Backend/ReplayScheduler/index.html +++ b/odoc/next/infer/Backend/ReplayScheduler/index.html @@ -2,4 +2,4 @@ ReplayScheduler (infer.Backend.ReplayScheduler)

    Module Backend.ReplayScheduler

    \ No newline at end of file + (Absint.TaskSchedulerTypes.target, 'a) IBase.ProcessPool.TaskGenerator.t \ No newline at end of file diff --git a/odoc/next/infer/Backend/SyntacticCallGraph/index.html b/odoc/next/infer/Backend/SyntacticCallGraph/index.html index 910c8af6ffd..947b0aa76f1 100644 --- a/odoc/next/infer/Backend/SyntacticCallGraph/index.html +++ b/odoc/next/infer/Backend/SyntacticCallGraph/index.html @@ -3,4 +3,4 @@ (IR.Procname.t -> IR.Procname.t list -> unit) -> unit

    run a function on every captured procedure, passing its list of syntactic callees

    task generator that works by

    • loading the syntactic call graph from the capture DB
    • restricting it to the reachable procs from the modified files
    • scheduling leaves only and removing them from the graph when analysed.
    val build_from_sources : IBase.SourceFile.t list -> CallGraph.t

    construct the syntactic call graph from the capture DB

    val to_dotty : CallGraph.t -> unit

    write out the given syntactic call graph into <results-dir>/syntactic-call-graph.dot

    \ No newline at end of file + (Absint.TaskSchedulerTypes.target, 'a) IBase.ProcessPool.TaskGenerator.t

    task generator that works by

    • loading the syntactic call graph from the capture DB
    • restricting it to the reachable procs from the modified files
    • scheduling leaves only and removing them from the graph when analysed.
    val build_from_sources : IBase.SourceFile.t list -> CallGraph.t

    construct the syntactic call graph from the capture DB

    val to_dotty : CallGraph.t -> unit

    write out the given syntactic call graph into <results-dir>/syntactic-call-graph.dot

    \ No newline at end of file diff --git a/odoc/next/infer/Biabduction/BuiltinDefn/index.html b/odoc/next/infer/Biabduction/BuiltinDefn/index.html index de358548d3f..02d0fb8ec0b 100644 --- a/odoc/next/infer/Biabduction/BuiltinDefn/index.html +++ b/odoc/next/infer/Biabduction/BuiltinDefn/index.html @@ -1,2 +1,2 @@ -BuiltinDefn (infer.Biabduction.BuiltinDefn)

    Module Biabduction.BuiltinDefn

    Models for the builtin functions supported

    include IR.BUILTINS.S with type t = Builtin.registered
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    val init : unit -> unit

    Clients of Builtin module should call this before Builtin module is used. WARNING: builtins are not guaranteed to be registered with the Builtin module until after init has been called.

    \ No newline at end of file +BuiltinDefn (infer.Biabduction.BuiltinDefn)

    Module Biabduction.BuiltinDefn

    Models for the builtin functions supported

    include IR.BUILTINS.S with type t = Builtin.registered
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __hack_throw : t
    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    val init : unit -> unit

    Clients of Builtin module should call this before Builtin module is used. WARNING: builtins are not guaranteed to be registered with the Builtin module until after init has been called.

    \ No newline at end of file diff --git a/odoc/next/infer/Checkers/Lineage/index.html b/odoc/next/infer/Checkers/Lineage/index.html index 6c0bc0f09ff..f0655dde51e 100644 --- a/odoc/next/infer/Checkers/Lineage/index.html +++ b/odoc/next/infer/Checkers/Lineage/index.html @@ -1,5 +1,6 @@ Lineage (infer.Checkers.Lineage)

    Module Checkers.Lineage

    \ No newline at end of file diff --git a/odoc/next/infer/ClangFrontend/CContext/CXXTemporarySet/index.html b/odoc/next/infer/ClangFrontend/CContext/CXXTemporarySet/index.html new file mode 100644 index 00000000000..0fd9fc77aaa --- /dev/null +++ b/odoc/next/infer/ClangFrontend/CContext/CXXTemporarySet/index.html @@ -0,0 +1,2 @@ + +CXXTemporarySet (infer.ClangFrontend.CContext.CXXTemporarySet)

    Module CContext.CXXTemporarySet

    include IStdlib.IStd.Caml.Set.S with type elt = cxx_temporary
    type elt = cxx_temporary
    type t
    val empty : t
    val is_empty : t -> bool
    val mem : elt -> t -> bool
    val add : elt -> t -> t
    val singleton : elt -> t
    val remove : elt -> t -> t
    val union : t -> t -> t
    val inter : t -> t -> t
    val disjoint : t -> t -> bool
    val diff : t -> t -> t
    val compare : t -> t -> int
    val equal : t -> t -> bool
    val subset : t -> t -> bool
    val iter : (elt -> unit) -> t -> unit
    val map : (elt -> elt) -> t -> t
    val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
    val for_all : (elt -> bool) -> t -> bool
    val exists : (elt -> bool) -> t -> bool
    val filter : (elt -> bool) -> t -> t
    val filter_map : (elt -> elt option) -> t -> t
    val partition : (elt -> bool) -> t -> t * t
    val cardinal : t -> int
    val elements : t -> elt list
    val min_elt : t -> elt
    val min_elt_opt : t -> elt option
    val max_elt : t -> elt
    val max_elt_opt : t -> elt option
    val choose : t -> elt
    val choose_opt : t -> elt option
    val split : elt -> t -> t * bool * t
    val find : elt -> t -> elt
    val find_opt : elt -> t -> elt option
    val find_first : (elt -> bool) -> t -> elt
    val find_first_opt : (elt -> bool) -> t -> elt option
    val find_last : (elt -> bool) -> t -> elt
    val find_last_opt : (elt -> bool) -> t -> elt option
    val of_list : elt list -> t
    val to_seq_from : elt -> t -> elt Stdlib.Seq.t
    val to_seq : t -> elt Stdlib.Seq.t
    val to_rev_seq : t -> elt Stdlib.Seq.t
    val add_seq : elt Stdlib.Seq.t -> t -> t
    val of_seq : elt Stdlib.Seq.t -> t
    val is_singleton_or_more : t -> elt IStdlib.IContainer.singleton_or_more
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val pp_element : IStdlib.PrettyPrintable.F.formatter -> elt -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IBase/Config/index.html b/odoc/next/infer/IBase/Config/index.html index 488c7c3f244..fd728d628dc 100644 --- a/odoc/next/infer/IBase/Config/index.html +++ b/odoc/next/infer/IBase/Config/index.html @@ -1,9 +1,9 @@ -Config (infer.IBase.Config)

    Module IBase.Config

    Configuration values: either constant, determined at compile time, or set at startup time by system calls, environment variables, or command line options

    type os_type =
    1. | Unix
    2. | Win32
    3. | Cygwin
    type build_system =
    1. | BAnt
    2. | BBuck
    3. | BBuck2
    4. | BClang
    5. | BErlc
    6. | BGradle
    7. | BHackc
    8. | BJava
    9. | BJavac
    10. | BKotlinc
    11. | BMake
    12. | BMvn
    13. | BNdk
    14. | BPython
    15. | BRebar3
    16. | BXcode
    type scheduler =
    1. | File
    2. | Restart
    3. | SyntacticCallGraph
    val equal_scheduler : scheduler -> scheduler -> bool
    val string_of_scheduler : scheduler -> string
    val build_system_of_exe_name : string -> build_system
    val string_of_build_system : build_system -> string
    val env_inside_maven : IStdlib.IStd.Unix.env

    Constant configuration values

    val anonymous_block_prefix : string
    val assign : string
    val biabduction_models_sql : string
    val biabduction_models_jar : string
    val bin_dir : string
    val bound_error_allowed_in_procedure_call : bool
    val clang_exe_aliases : string list
    val clang_initializer_prefix : string
    val clang_inner_destructor_prefix : string
    val clang_plugin_path : string
    val default_failure_name : string
    val dotty_frontend_output : string
    val etc_dir : string
    val fail_on_issue_exit_code : int
    val fcp_dir : string
    val idempotent_getters : bool
    val initial_analysis_time : float
    val is_running_unit_test : bool

    whether the infer executable looks like we are just running infer unit tests

    val ivar_attributes : string
    val java_lambda_marker_infix_generated_by_javalib : string

    marker to recognize methods generated by javalib to eliminate lambdas

    val java_lambda_marker_prefix_generated_by_javac : string

    marker to recognize methods generated by javac to build closures

    val kotlin_source_extension : string
    val lib_dir : string
    val max_narrows : int
    val max_widens : int
    val meet_level : int
    val nsnotification_center_checker_backend : bool
    val os_type : os_type
    val pp_version : Stdlib.Format.formatter -> unit -> unit
    val property_attributes : string
    val report_nullable_inconsistency : bool
    val save_compact_summaries : bool
    val smt_output : bool
    val unsafe_unret : string
    val weak : string
    val allow_listed_cpp_classes : string list
    val allow_listed_cpp_methods : string list
    val wrappers_dir : string

    Configuration values specified by command-line options

    val abstract_pulse_models_for_erlang : bool
    val analysis_schedule_file : string option
    val annotation_reachability_cxx : Yojson.Basic.t
    val run_as_child : int option
    val annotation_reachability_cxx_sources : Yojson.Basic.t
    val annotation_reachability_custom_pairs : Yojson.Basic.t
    val append_buck_flavors : string list
    val biabduction_abs_struct : int
    val biabduction_abs_val : int
    val biabduction_allow_leak : bool
    val biabduction_array_level : int
    val biabduction_models_mode : bool
    val biabduction_iterations : int
    val biabduction_join_cond : int
    val biabduction_memleak_buckets : +Config (infer.IBase.Config)

    Module IBase.Config

    Configuration values: either constant, determined at compile time, or set at startup time by system calls, environment variables, or command line options

    type os_type =
    1. | Unix
    2. | Win32
    3. | Cygwin
    type build_system =
    1. | BAnt
    2. | BBuck
    3. | BBuck2
    4. | BClang
    5. | BErlc
    6. | BGradle
    7. | BHackc
    8. | BJava
    9. | BJavac
    10. | BKotlinc
    11. | BMake
    12. | BMvn
    13. | BNdk
    14. | BPython
    15. | BRebar3
    16. | BXcode
    type scheduler =
    1. | File
    2. | Restart
    3. | SyntacticCallGraph
    val equal_scheduler : scheduler -> scheduler -> bool
    val string_of_scheduler : scheduler -> string
    val build_system_of_exe_name : string -> build_system
    val string_of_build_system : build_system -> string
    val env_inside_maven : IStdlib.IStd.Unix.env

    Constant configuration values

    val anonymous_block_prefix : string
    val assign : string
    val biabduction_models_sql : string
    val biabduction_models_jar : string
    val bin_dir : string
    val bound_error_allowed_in_procedure_call : bool
    val clang_exe_aliases : string list
    val clang_initializer_prefix : string
    val clang_inner_destructor_prefix : string
    val clang_plugin_path : string
    val default_failure_name : string
    val dotty_frontend_output : string
    val etc_dir : string
    val fail_on_issue_exit_code : int
    val fcp_dir : string
    val idempotent_getters : bool
    val initial_analysis_time : float
    val is_running_unit_test : bool

    whether the infer executable looks like we are just running infer unit tests

    val ivar_attributes : string
    val java_lambda_marker_infix_generated_by_javalib : string

    marker to recognize methods generated by javalib to eliminate lambdas

    val java_lambda_marker_prefix_generated_by_javac : string

    marker to recognize methods generated by javac to build closures

    val kotlin_source_extension : string
    val lib_dir : string
    val max_narrows : int
    val max_widens : int
    val meet_level : int
    val nsnotification_center_checker_backend : bool
    val os_type : os_type
    val pp_version : Stdlib.Format.formatter -> unit -> unit
    val property_attributes : string
    val report_nullable_inconsistency : bool
    val save_compact_summaries : bool
    val smt_output : bool
    val unsafe_unret : string
    val weak : string
    val allow_listed_cpp_classes : string list
    val allow_listed_cpp_methods : string list
    val wrappers_dir : string

    Configuration values specified by command-line options

    val abstract_pulse_models_for_erlang : bool
    val analysis_schedule_file : string option
    val annotation_reachability_cxx : Yojson.Basic.t
    val run_as_child : int option
    val annotation_reachability_cxx_sources : Yojson.Basic.t
    val annotation_reachability_custom_pairs : Yojson.Basic.t
    val annotation_reachability_no_allocation : bool
    val annotation_reachability_expensive : bool
    val append_buck_flavors : string list
    val biabduction_abs_struct : int
    val biabduction_abs_val : int
    val biabduction_allow_leak : bool
    val biabduction_array_level : int
    val biabduction_models_mode : bool
    val biabduction_iterations : int
    val biabduction_join_cond : int
    val biabduction_memleak_buckets : [ `MLeak_all | `MLeak_arc | `MLeak_cf | `MLeak_cpp | `MLeak_no_arc | `MLeak_unknown ] - list
    val biabduction_monitor_prop_size : bool
    val biabduction_nelseg : bool
    val biabduction_only_footprint : bool
    val biabduction_seconds_per_iteration : float option
    val biabduction_symops_per_iteration : int option
    val biabduction_trace_join : bool
    val biabduction_trace_rearrange : bool
    val biabduction_type_size : bool
    val biabduction_unsafe_malloc : bool
    val biabduction_worklist_mode : int
    val biabduction_write_dotty : bool
    val bo_debug : int
    val bo_field_depth_limit : int option
    val bo_max_cfg_size : int
    val bo_sound_unknown_sets_join : bool
    val bo_bottom_as_default : bool
    val bo_context_sensitive_allocsites : bool
    val bo_assume_void : bool
    val bo_exit_frontend_gener_vars : bool
    val bootclasspath : string option
    val buck : bool
    val buck2_build_args : string list
    val buck2_build_args_no_inline : string list
    val buck2_bxl_target : string option
    val buck2_inferconfig_target : string option
    val buck2_isolation_dir : string option
    val buck2_query_deps : bool
    val buck2_root : string
    val buck2_use_bxl : bool
    val buck_block_list : string list
    val buck_build_args : string list
    val buck_build_args_no_inline : string list
    val buck_cache_mode : bool
    val buck_clang_use_toolchain_config : bool
    val buck_dependency_depth : int option
    val buck_java_suppress_config : bool
    val buck_java_heap_size_gb : int option
    val buck_merge_all_deps : bool
    val buck_mode : BuckMode.t option
    val buck_out : string
    val buck_out_gen : string
    val buck_targets_block_list : string list
    val bxl_file_capture : bool
    val capture : bool
    val capture_block_list : string * Yojson.Basic.t
    val capture_textual : string list
    val censor_report : ((bool * Str.regexp) * (bool * Str.regexp) * string) list
    val cfg_json : string option
    val changed_files_index : string option
    val check_version : string option
    val clang_ast_file : [ `Biniou of string | `Yojson of string ] option
    val clang_compound_literal_init_limit : int
    val clang_extra_flags : string list
    val clang_block_listed_flags : string list
    val clang_block_listed_flags_with_arg : string list
    val clang_frontend_action_string : string
    val clang_ignore_regex : Str.regexp option
    val clang_isystem_to_override_regex : Str.regexp option
    val clang_idirafter_to_override_regex : Str.regexp option
    val clang_libcxx_include_to_override_regex : string option
    val classpath : string option
    val compaction_if_heap_greater_equal_to_GB : int
    val compaction_minimum_interval_s : int
    val complete_capture_from : string option
    val config_impact_config_field_patterns : Re.Str.regexp list
    val config_impact_config_function_patterns : Re.Str.regexp list
    val config_impact_config_param_patterns : Re.Str.regexp list
    val config_impact_current : string option
    val config_impact_data_file : string option
    val config_impact_issues_tests : string option
    val config_impact_max_callees_to_print : int
    val config_impact_previous : string option
    val config_impact_strict_mode : bool
    val config_impact_strict_mode_paths : Str.regexp list
    val config_impact_test_paths : Str.regexp list
    val continue_analysis : bool
    val continue_capture : bool
    val costs_current : string option
    val cost_issues_tests : string option
    val cost_scuba_logging : bool
    val costs_previous : string option
    val cost_suppress_func_ptr : bool
    val cxx : bool
    val cxx_scope_guards : Yojson.Basic.t
    val liveness_block_list_var_regex : Str.regexp option
    val data_flow_queries_on_topl : string list
    val dbwriter : bool
    val deduplicate : bool
    val debug_exceptions : bool
    val debug_level_analysis : int
    val debug_level_capture : int
    val debug_level_test_determinator : int
    val debug_mode : bool
    val dependency_mode : bool
    val developer_mode : bool
    val differential_filter_files : string option
    val differential_filter_set : [ `Introduced | `Fixed | `Preexisting ] list
    val dotty_cfg_libs : bool
    val dump_duplicate_symbols : bool
    val dump_textual : bool
    val dynamic_dispatch_json_file_path : string option
    val erlang_ast_dir : string option
    val erlang_check_return : bool
    val erlang_list_unfold_depth : int
    val erlang_reliability : bool
    val erlang_skip_compile : bool
    val erlang_with_otp_specs : bool
    val extract_capture_from : string option
    val fail_on_bug : bool
    val fcp_apple_clang : string option
    val fcp_syntax_only : bool
    val file_renamings : string option
    val files_to_analyze_index : string option
    val filter_paths : bool
    val filtering : bool
    val force_delete_results_dir : bool
    val force_integration : build_system option
    val from_json_report : string
    val from_json_config_impact_report : string
    val from_json_costs_report : string
    val frontend_stats : bool
    val frontend_tests : bool
    val generated_classes : string option
    val genrule_mode : bool
    val global_tenv : bool
    val hack_naming_table : string option
    val hackc_binary : string option
    val hack_builtin_models : string
    val hack_models : string list
    val help_checker : Checker.t list
    val help_issue_type : IssueType.t list
    val hoisting_report_only_expensive : bool
    val html : bool
    val infer_binary : string

    absolute canonicalized path to the current executable

    val icfg_dotty_outfile : string option
    val impurity_report_immutable_modifications : bool
    val incremental_analysis : bool
    val inline_func_pointer_for_testing : string option
    val infer_is_clang : bool
    val infer_is_javac : bool
    val invalidate_only : bool
    val implicit_sdk_root : string option
    val inclusive_cost : bool
    val inferconfig_file : string option
    val is_checker_enabled : Checker.t -> bool
    val issues_tests : string option
    val issues_tests_fields : IssuesTestField.t list
    val java_debug_source_file_info : string option
    val java_jar_compiler : string option
    val java_reflection : bool
    val java_source_parser_experimental : bool
    val java_version : int option
    val javac_classes_out : string
    val job_id : string option
    val jobs : int
    val keep_going : bool
    val kotlin_capture : bool
    val list_checkers : bool
    val list_issue_types : bool
    val liveness_dangerous_classes : Yojson.Basic.t
    val liveness_ignored_constant : string list
    val load_average : float option
    val lock_model : Yojson.Basic.t
    val log_missing_deps : bool
    val margin_html : int
    val mark_unchanged_procs : bool
    val mask_sajwa_exceptions : bool
    val max_nesting : int option
    val memtrace_analysis : bool
    val memtrace_sampling_rate : float
    val merge_capture : string list
    val merge_report : string list
    val merge_summaries : string list
    val method_decls_info : string option
    val modeled_expensive : string * Yojson.Basic.t
    val modified_lines : string option
    val never_returning_null : string * Yojson.Basic.t
    val no_censor_report : Str.regexp list
    val no_translate_libs : bool
    val nullable_annotation : string option
    val oom_threshold : int option
    val only_cheap_debug : bool
    val pmd_xml : bool
    val preanalysis_html : bool
    val print_active_checkers : bool
    val print_builtins : bool
    val print_jbir : bool
    val print_logs : bool
    val print_types : bool
    val print_using_diff : bool
    val procedures : bool
    val procedures_attributes : bool
    val procedures_callees : bool
    val procedures_call_graph : bool
    val procedures_cfg : bool
    val procedures_definedness : bool
    val procedures_filter : string option
    val procedures_name : bool
    val procedures_source_file : bool
    val procedures_summary : bool
    val procedures_summary_json : bool
    val procedures_summary_skip_empty : bool
    val process_clang_ast : bool
    val profiler_samples : string option
    val progress_bar : [ `MultiLine | `Plain | `Quiet ]
    val project_root : string
    val pulse_cut_to_one_path_procedures_pattern : Str.regexp option
    val pulse_force_continue : bool
    val pulse_havoc_arguments : bool
    val pulse_inline_global_init_func_pointer : bool
    val pulse_intraprocedural_only : bool
    val pulse_max_cfg_size : int
    val pulse_max_disjuncts : int
    val pulse_max_heap : int option
    val pulse_model_abort : string list
    val pulse_model_alloc_pattern : Str.regexp option
    val pulse_model_cheap_copy_type : Str.regexp option
    val pulse_model_free_pattern : Str.regexp option
    val pulse_model_malloc_pattern : Str.regexp option
    val pulse_unsafe_malloc : bool
    val pulse_model_realloc_pattern : Str.regexp option
    val pulse_model_release_pattern : Str.regexp option
    val pulse_model_returns_copy_pattern : Str.regexp option
    val pulse_model_return_first_arg : Str.regexp option
    val pulse_model_return_this : Str.regexp option
    val pulse_model_return_nonnull : Str.regexp option
    val pulse_model_skip_pattern : Str.regexp option
    val pulse_models_for_erlang : string list
    val pulse_monitor_transitive_callees : bool
    val pulse_monitor_transitive_missed_captures : bool
    val pulse_prevent_non_disj_top : bool
    val pulse_report_flows_from_taint_source : string option
    val pulse_report_flows_to_taint_sink : string option
    val pulse_model_transfer_ownership_namespace : (string * string) list
    val pulse_model_transfer_ownership : string list
    val pulse_report_latent_issues : bool
    val pulse_report_issues_for_tests : bool
    val pulse_sanity_checks : bool
    val pulse_recency_limit : int
    val pulse_scuba_logging : bool
    val pulse_skip_procedures : Str.regexp option
    val pulse_specialization_limit : int
    val pulse_specialization_iteration_limit : int
    val pulse_specialization_partial : bool
    val pulse_taint_config : pulse_taint_config
    val pulse_taint_check_history : bool
    val pulse_taint_short_traces : bool
    val pulse_taint_skip_sources : bool
    val pulse_transitive_access_config : string option
    val pulse_transitive_access_verbose : bool
    val pulse_widen_threshold : int
    val pulse_nullsafe_report_npe : bool
    val pulse_nullsafe_report_npe_as_separate_issue_type : bool
    val pulse_log_summary_count : bool
    val pure_by_default : bool
    val pyc_file : string list
    val python_builtin_models : string
    val quandary_endpoints : Yojson.Basic.t
    val quandary_sanitizers : Yojson.Basic.t
    val quandary_show_passthroughs : bool
    val quandary_sinks : Yojson.Basic.t
    val quandary_sources : Yojson.Basic.t
    val quiet : bool
    val racerd_always_report_java : bool
    val racerd_guardedby : bool
    val racerd_ignore_classes : IStdlib.IStd.String.Set.t
    val reactive_mode : bool
    val reanalyze : bool
    val relative_path_backtrack : int
    val remodel_class : string option
    val replay_analysis_schedule : bool
    val replay_ondemand_should_error : bool
    val report : bool
    val report_block_list_files_containing : string list
    val report_console_limit : int option
    val report_current : string option
    val report_custom_error : bool
    val report_force_relative_path : bool
    val report_formatter : [ `No_formatter | `Phabricator_formatter ]
    val report_path_regex_block_list : string list
    val report_path_regex_allow_list : string list
    val report_previous : string option
    val report_suppress_errors : string list
    val reports_include_ml_loc : bool
    val rest : string list
    val results_dir : string
    val sarif : bool
    val scheduler : scheduler
    val scope_leakage_config : Yojson.Basic.t
    val scuba_logging : bool
    val scuba_normals : string IStdlib.IStd.String.Map.t
    val scuba_tags : string list IStdlib.IStd.String.Map.t
    val select : [ `All | `Select of int ] option
    val show_buckets : bool
    val shrink_analysis_db : bool
    val lineage_include_builtins : bool
    val lineage_field_depth : int
    val lineage_prevent_cycles : bool
    val lineage_field_width : int option
    val lineage_variant_width : int
    val lineage_json_report : bool
    val lineage_keep_temporaries : bool
    val lineage_field_max_cfg_size : int option
    val lineage_max_cfg_size : int option
    val lineage_dedup : bool
    val lineage_seed : int
    val siof_check_iostreams : bool
    val siof_safe_methods : string list
    val skip_analysis_in_path : Str.regexp option
    val skip_analysis_in_path_skips_compilation : bool
    val skip_duplicated_types : bool
    val skip_non_capture_clang_commands : bool
    val skip_translation_headers : string list
    val source_files : bool
    val source_files_call_graph : bool
    val source_files_call_graph_partition : int option
    val source_files_cfg : bool
    val source_files_filter : string option
    val source_files_freshly_captured : bool
    val source_files_procedure_names : bool
    val source_files_type_environment : bool
    val source_preview : bool
    val sourcepath : string option
    val sources : string list
    val sqlite_cache_size : int
    val sqlite_page_size : int
    val sqlite_lock_timeout : int
    val sqlite_max_blob_size : int
    val sqlite_mmap_size : int
    val sqlite_vfs : string option
    val starvation_skip_analysis : Yojson.Basic.t
    val starvation_strict_mode : bool
    val starvation_whole_program : bool
    val store_analysis_schedule : bool
    val subtype_multirange : bool
    val suffix_match_changed_files : bool
    val summaries_caches_max_size : int
    val suppress_lint_ignore_types : bool
    val tenv_json : string option
    val test_determinator : bool
    val export_changed_functions : bool
    val testing_mode : bool
    val threadsafe_aliases : Yojson.Basic.t
    val timeout : float option
    val top_longest_proc_duration_size : int option
    val topl_max_conjuncts : int
    val topl_max_disjuncts : int
    val topl_properties : ToplAst.t list
    val topl_report_latent_issues : bool
    val trace_absarray : bool
    val trace_error : bool
    val trace_events : bool
    val trace_ondemand : bool
    val trace_topl : bool
    val uninit_interproc : bool
    val unix_fork : bool
    val workspace : string option
    val write_html : bool
    val write_html_allow_list_regex : string list
    val write_website : string option
    val xcode_developer_dir : string option
    val xcode_isysroot_suffix : string option
    val xcpretty : bool

    Configuration values derived from command-line options

    val toplevel_results_dir : string

    In some integrations, eg Buck, infer subprocesses started by the build system (started by the toplevel infer process) will have their own results directory; this points to the results directory of the toplevel infer process, which can be useful for, eg, storing debug info. In other cases this is equal to results_dir.

    val java_package_is_external : string -> bool

    Check if a Java package is external to the repository

    val scuba_execution_id : IStdlib.IStd.Int64.t option

    a random number to (hopefully) uniquely identify this run

    val is_originator : bool

    is the current process (forked from) the root of the Infer process tree

    Global variables with initial values specified by command-line options

    val clang_compilation_dbs : [ `Escaped of string | `Raw of string ] list
    \ No newline at end of file + list
    val biabduction_monitor_prop_size : bool
    val biabduction_nelseg : bool
    val biabduction_only_footprint : bool
    val biabduction_seconds_per_iteration : float option
    val biabduction_symops_per_iteration : int option
    val biabduction_trace_join : bool
    val biabduction_trace_rearrange : bool
    val biabduction_type_size : bool
    val biabduction_unsafe_malloc : bool
    val biabduction_worklist_mode : int
    val biabduction_write_dotty : bool
    val bo_debug : int
    val bo_field_depth_limit : int option
    val bo_max_cfg_size : int
    val bo_sound_unknown_sets_join : bool
    val bo_bottom_as_default : bool
    val bo_context_sensitive_allocsites : bool
    val bo_assume_void : bool
    val bo_exit_frontend_gener_vars : bool
    val bootclasspath : string option
    val buck : bool
    val buck2_build_args : string list
    val buck2_build_args_no_inline : string list
    val buck2_bxl_target : string option
    val buck2_inferconfig_target : string option
    val buck2_isolation_dir : string option
    val buck2_query_deps : bool
    val buck2_root : string
    val buck2_use_bxl : bool
    val buck_block_list : string list
    val buck_build_args : string list
    val buck_build_args_no_inline : string list
    val buck_cache_mode : bool
    val buck_clang_use_toolchain_config : bool
    val buck_dependency_depth : int option
    val buck_java_suppress_config : bool
    val buck_java_heap_size_gb : int option
    val buck_merge_all_deps : bool
    val buck_mode : BuckMode.t option
    val buck_out : string
    val buck_out_gen : string
    val buck_targets_block_list : string list
    val bxl_file_capture : bool
    val capture : bool
    val capture_block_list : string * Yojson.Basic.t
    val capture_textual : string list
    val censor_report : ((bool * Str.regexp) * (bool * Str.regexp) * string) list
    val cfg_json : string option
    val changed_files_index : string option
    val check_version : string option
    val clang_ast_file : [ `Biniou of string | `Yojson of string ] option
    val clang_compound_literal_init_limit : int
    val clang_extra_flags : string list
    val clang_block_listed_flags : string list
    val clang_block_listed_flags_with_arg : string list
    val clang_frontend_action_string : string
    val clang_ignore_regex : Str.regexp option
    val clang_isystem_to_override_regex : Str.regexp option
    val clang_idirafter_to_override_regex : Str.regexp option
    val clang_libcxx_include_to_override_regex : string option
    val classpath : string option
    val compaction_if_heap_greater_equal_to_GB : int
    val compaction_minimum_interval_s : int
    val complete_capture_from : string option
    val config_impact_config_field_patterns : Re.Str.regexp list
    val config_impact_config_function_patterns : Re.Str.regexp list
    val config_impact_config_param_patterns : Re.Str.regexp list
    val config_impact_current : string option
    val config_impact_data_file : string option
    val config_impact_issues_tests : string option
    val config_impact_max_callees_to_print : int
    val config_impact_previous : string option
    val config_impact_strict_mode : bool
    val config_impact_strict_mode_paths : Str.regexp list
    val config_impact_test_paths : Str.regexp list
    val continue_analysis : bool
    val continue_capture : bool
    val costs_current : string option
    val cost_issues_tests : string option
    val cost_scuba_logging : bool
    val costs_previous : string option
    val cost_suppress_func_ptr : bool
    val cxx : bool
    val cxx_scope_guards : Yojson.Basic.t
    val liveness_block_list_var_regex : Str.regexp option
    val data_flow_queries_on_topl : string list
    val dbwriter : bool
    val deduplicate : bool
    val debug_exceptions : bool
    val debug_level_analysis : int
    val debug_level_capture : int
    val debug_level_test_determinator : int
    val debug_mode : bool
    val dependency_mode : bool
    val developer_mode : bool
    val differential_filter_files : string option
    val differential_filter_set : [ `Introduced | `Fixed | `Preexisting ] list
    val dotty_cfg_libs : bool
    val dump_duplicate_symbols : bool
    val dump_textual : bool
    val dynamic_dispatch_json_file_path : string option
    val erlang_ast_dir : string option
    val erlang_check_return : bool
    val erlang_list_unfold_depth : int
    val erlang_reliability : bool
    val erlang_skip_compile : bool
    val erlang_with_otp_specs : bool
    val extract_capture_from : string option
    val fail_on_bug : bool
    val fcp_apple_clang : string option
    val fcp_syntax_only : bool
    val file_renamings : string option
    val files_to_analyze_index : string option
    val filter_paths : bool
    val filtering : bool
    val force_delete_results_dir : bool
    val force_integration : build_system option
    val from_json_report : string
    val from_json_config_impact_report : string
    val from_json_costs_report : string
    val frontend_stats : bool
    val frontend_tests : bool
    val generated_classes : string option
    val genrule_mode : bool
    val global_tenv : bool
    val hack_naming_table : string option
    val hackc_binary : string option
    val hack_builtin_models : string
    val hack_models : string list
    val help_checker : Checker.t list
    val help_issue_type : IssueType.t list
    val hoisting_report_only_expensive : bool
    val html : bool
    val infer_binary : string

    absolute canonicalized path to the current executable

    val icfg_dotty_outfile : string option
    val impurity_report_immutable_modifications : bool
    val incremental_analysis : bool
    val inline_func_pointer_for_testing : string option
    val infer_is_clang : bool
    val infer_is_javac : bool
    val invalidate_only : bool
    val implicit_sdk_root : string option
    val inclusive_cost : bool
    val inferconfig_file : string option
    val is_checker_enabled : Checker.t -> bool
    val issues_tests : string option
    val issues_tests_fields : IssuesTestField.t list
    val java_debug_source_file_info : string option
    val java_jar_compiler : string option
    val java_reflection : bool
    val java_source_parser_experimental : bool
    val java_version : int option
    val javac_classes_out : string
    val job_id : string option
    val jobs : int
    val keep_going : bool
    val kotlin_capture : bool
    val list_checkers : bool
    val list_issue_types : bool
    val liveness_dangerous_classes : Yojson.Basic.t
    val liveness_ignored_constant : string list
    val load_average : float option
    val lock_model : Yojson.Basic.t
    val log_missing_deps : bool
    val margin_html : int
    val mark_unchanged_procs : bool
    val mask_sajwa_exceptions : bool
    val max_nesting : int option
    val memtrace_analysis : bool
    val memtrace_sampling_rate : float
    val merge_capture : string list
    val merge_report : string list
    val merge_summaries : string list
    val method_decls_info : string option
    val modeled_expensive : string * Yojson.Basic.t
    val modified_lines : string option
    val never_returning_null : string * Yojson.Basic.t
    val no_censor_report : Str.regexp list
    val no_translate_libs : bool
    val nullable_annotation : string option
    val oom_threshold : int option
    val only_cheap_debug : bool
    val pmd_xml : bool
    val preanalysis_html : bool
    val print_active_checkers : bool
    val print_builtins : bool
    val print_jbir : bool
    val print_logs : bool
    val print_types : bool
    val print_using_diff : bool
    val procedures : bool
    val procedures_attributes : bool
    val procedures_callees : bool
    val procedures_call_graph : bool
    val procedures_cfg : bool
    val procedures_definedness : bool
    val procedures_filter : string option
    val procedures_name : bool
    val procedures_source_file : bool
    val procedures_summary : bool
    val procedures_summary_json : bool
    val procedures_summary_skip_empty : bool
    val process_clang_ast : bool
    val profiler_samples : string option
    val progress_bar : [ `MultiLine | `Plain | `Quiet ]
    val project_root : string
    val pulse_cut_to_one_path_procedures_pattern : Str.regexp option
    val pulse_force_continue : bool
    val pulse_havoc_arguments : bool
    val pulse_inline_global_init_func_pointer : bool
    val pulse_intraprocedural_only : bool
    val pulse_max_cfg_size : int
    val pulse_max_disjuncts : int
    val pulse_max_heap : int option
    val pulse_model_abort : string list
    val pulse_model_alloc_pattern : Str.regexp option
    val pulse_model_cheap_copy_type : Str.regexp option
    val pulse_model_free_pattern : Str.regexp option
    val pulse_model_malloc_pattern : Str.regexp option
    val pulse_unsafe_malloc : bool
    val pulse_model_realloc_pattern : Str.regexp option
    val pulse_model_release_pattern : Str.regexp option
    val pulse_model_returns_copy_pattern : Str.regexp option
    val pulse_model_return_first_arg : Str.regexp option
    val pulse_model_return_this : Str.regexp option
    val pulse_model_return_nonnull : Str.regexp option
    val pulse_model_skip_pattern : Str.regexp option
    val pulse_models_for_erlang : string list
    val pulse_monitor_transitive_callees : bool
    val pulse_monitor_transitive_missed_captures : bool
    val pulse_prevent_non_disj_top : bool
    val pulse_report_flows_from_taint_source : string option
    val pulse_report_flows_to_taint_sink : string option
    val pulse_model_transfer_ownership_namespace : (string * string) list
    val pulse_model_transfer_ownership : string list
    val pulse_report_latent_issues : bool
    val pulse_report_issues_for_tests : bool
    val pulse_sanity_checks : bool
    val pulse_recency_limit : int
    val pulse_scuba_logging : bool
    val pulse_skip_procedures : Str.regexp option
    val pulse_specialization_limit : int
    val pulse_specialization_iteration_limit : int
    val pulse_specialization_partial : bool
    val pulse_taint_config : pulse_taint_config
    val pulse_taint_check_history : bool
    val pulse_taint_short_traces : bool
    val pulse_taint_skip_sources : bool
    val pulse_transitive_access_config : string list
    val pulse_transitive_access_verbose : bool
    val pulse_widen_threshold : int
    val pulse_nullsafe_report_npe : bool
    val pulse_nullsafe_report_npe_as_separate_issue_type : bool
    val pulse_log_summary_count : bool
    val pure_by_default : bool
    val pyc_file : string list
    val python_builtin_models : string
    val quandary_endpoints : Yojson.Basic.t
    val quandary_sanitizers : Yojson.Basic.t
    val quandary_show_passthroughs : bool
    val quandary_sinks : Yojson.Basic.t
    val quandary_sources : Yojson.Basic.t
    val quiet : bool
    val racerd_always_report_java : bool
    val racerd_guardedby : bool
    val racerd_ignore_classes : IStdlib.IStd.String.Set.t
    val reactive_mode : bool
    val reanalyze : bool
    val relative_path_backtrack : int
    val remodel_class : string option
    val replay_analysis_schedule : bool
    val replay_ondemand_should_error : bool
    val report : bool
    val report_block_list_files_containing : string list
    val report_console_limit : int option
    val report_current : string option
    val report_custom_error : bool
    val report_force_relative_path : bool
    val report_formatter : [ `No_formatter | `Phabricator_formatter ]
    val report_path_regex_block_list : string list
    val report_path_regex_allow_list : string list
    val report_previous : string option
    val report_suppress_errors : string list
    val reports_include_ml_loc : bool
    val rest : string list
    val results_dir : string
    val sarif : bool
    val scheduler : scheduler
    val scope_leakage_config : Yojson.Basic.t
    val scuba_logging : bool
    val scuba_normals : string IStdlib.IStd.String.Map.t
    val scuba_tags : string list IStdlib.IStd.String.Map.t
    val select : [ `All | `Select of int ] option
    val show_buckets : bool
    val shrink_analysis_db : bool
    val lineage_include_builtins : bool
    val lineage_field_depth : int
    val lineage_prevent_cycles : bool
    val lineage_field_width : int option
    val lineage_variant_width : int
    val lineage_json_report : bool
    val lineage_keep_temporaries : bool
    val lineage_field_max_cfg_size : int option
    val lineage_max_cfg_size : int option
    val lineage_dedup : bool
    val lineage_seed : int
    val siof_check_iostreams : bool
    val siof_safe_methods : string list
    val skip_analysis_in_path : Str.regexp option
    val skip_analysis_in_path_skips_compilation : bool
    val skip_duplicated_types : bool
    val skip_non_capture_clang_commands : bool
    val skip_translation_headers : string list
    val source_files : bool
    val source_files_call_graph : bool
    val source_files_call_graph_partition : int option
    val source_files_cfg : bool
    val source_files_filter : string option
    val source_files_freshly_captured : bool
    val source_files_procedure_names : bool
    val source_files_type_environment : bool
    val source_preview : bool
    val sourcepath : string option
    val sources : string list
    val sqlite_cache_size : int
    val sqlite_page_size : int
    val sqlite_lock_timeout : int
    val sqlite_max_blob_size : int
    val sqlite_mmap_size : int
    val sqlite_vfs : string option
    val starvation_skip_analysis : Yojson.Basic.t
    val starvation_strict_mode : bool
    val starvation_whole_program : bool
    val store_analysis_schedule : bool
    val subtype_multirange : bool
    val suffix_match_changed_files : bool
    val summaries_caches_max_size : int
    val suppress_lint_ignore_types : bool
    val tenv_json : string option
    val test_determinator : bool
    val export_changed_functions : bool
    val testing_mode : bool
    val threadsafe_aliases : Yojson.Basic.t
    val timeout : float option
    val top_longest_proc_duration_size : int option
    val topl_max_conjuncts : int
    val topl_max_disjuncts : int
    val topl_properties : ToplAst.t list
    val topl_report_latent_issues : bool
    val trace_absarray : bool
    val trace_error : bool
    val trace_events : bool
    val trace_ondemand : bool
    val trace_topl : bool
    val uninit_interproc : bool
    val unix_fork : bool
    val workspace : string option
    val write_html : bool
    val write_html_allow_list_regex : string list
    val write_website : string option
    val xcode_developer_dir : string option
    val xcode_isysroot_suffix : string option
    val xcpretty : bool

    Configuration values derived from command-line options

    val toplevel_results_dir : string

    In some integrations, eg Buck, infer subprocesses started by the build system (started by the toplevel infer process) will have their own results directory; this points to the results directory of the toplevel infer process, which can be useful for, eg, storing debug info. In other cases this is equal to results_dir.

    val java_package_is_external : string -> bool

    Check if a Java package is external to the repository

    val scuba_execution_id : IStdlib.IStd.Int64.t option

    a random number to (hopefully) uniquely identify this run

    val is_originator : bool

    is the current process (forked from) the root of the Infer process tree

    Global variables with initial values specified by command-line options

    val clang_compilation_dbs : [ `Escaped of string | `Raw of string ] list
    \ No newline at end of file diff --git a/odoc/next/infer/IBase/IssueType/index.html b/odoc/next/infer/IBase/IssueType/index.html index 6d9a76021d4..8e9d7bef475 100644 --- a/odoc/next/infer/IBase/IssueType/index.html +++ b/odoc/next/infer/IBase/IssueType/index.html @@ -6,4 +6,4 @@ ?user_documentation:string -> severity -> Checker.t -> - t

    Create a new issue and register it in the list of all issues. NOTE: if the issue with the same string id is already registered, overrides `hum` but DOES NOT override `enabled`. This trick allows to deal with disabling/enabling dynamic issues from the config, when we don't know all params yet. Thus, the human-readable description can be updated when we encounter the definition of the issue type.

    val checker_can_report : Checker.t -> t -> bool

    Whether the issue was registered as coming from the given checker. Important to call this before reporting to keep documentation accurate.

    val set_enabled : t -> bool -> unit
    val abduction_case_not_implemented : t
    val arbitrary_code_execution_under_lock : t
    val array_of_pointsto : t
    val array_out_of_bounds_l1 : t
    val array_out_of_bounds_l2 : t
    val array_out_of_bounds_l3 : t
    val assert_failure : t
    val bad_footprint : t
    val bad_arg : latent:bool -> t
    val bad_key : latent:bool -> t
    val bad_map : latent:bool -> t
    val bad_record : latent:bool -> t
    val bad_return : latent:bool -> t
    val biabduction_analysis_stops : t
    val biabduction_retain_cycle : t
    val block_parameter_not_null_checked : t
    val buffer_overrun_l1 : t
    val buffer_overrun_l2 : t
    val buffer_overrun_l3 : t
    val buffer_overrun_l4 : t
    val buffer_overrun_l5 : t
    val buffer_overrun_s2 : t
    val buffer_overrun_u5 : t
    val cannot_star : t
    val captured_strong_self : t
    val checkers_allocates_memory : t

    Warning name when a performance critical method directly or indirectly calls a method allocating memory

    val checkers_annotation_reachability_error : t
    val checkers_calls_expensive_method : t

    Warning name when a performance critical method directly or indirectly calls a method annotatd as expensive

    val checkers_expensive_overrides_unexpensive : t

    Warning name for the subtyping rule: method not annotated as expensive cannot be overridden by a method annotated as expensive

    val checkers_fragment_retain_view : t
    val checkers_printf_args : t
    val class_cast_exception : t
    val complexity_increase : kind:CostKind.t -> is_on_ui_thread:bool -> t
    val condition_always_false : t
    val condition_always_true : t
    val config_impact_analysis : t
    val config_impact_analysis_strict : t
    val pulse_config_usage : t
    val pulse_const_refable : t
    val constant_address_dereference : latent:bool -> t
    val cxx_ref_captured_in_block : t
    val create_intent_from_uri : t
    val cross_site_scripting : t
    val dangling_pointer_dereference : t
    val dangling_pointer_dereference_maybe : t
    val data_flow_to_sink : t
    val datalog_fact : t
    val dead_store : t
    val deadlock : t
    val divide_by_zero : t
    val do_not_report : t

    an issue type that should never be reported

    val empty_vector_access : t
    val exposed_insecure_intent_handling : t
    val expensive_cost_call : kind:CostKind.t -> t
    val failure_exe : t
    val guardedby_violation : t
    val impure_function : t
    val inefficient_keyset_iterator : t
    val inferbo_alloc_is_big : t
    val inferbo_alloc_is_negative : t
    val inferbo_alloc_is_zero : t
    val inferbo_alloc_may_be_big : t
    val inferbo_alloc_may_be_negative : t
    val infinite_cost_call : kind:CostKind.t -> t
    val inherently_dangerous_function : t
    val insecure_intent_handling : t
    val integer_overflow_l1 : t
    val integer_overflow_l2 : t
    val integer_overflow_l5 : t
    val integer_overflow_u5 : t
    val interface_not_thread_safe : t
    val internal_error : t
    val invalid_sil : t
    val invariant_call : t
    val ipc_on_ui_thread : t
    val javascript_injection : t
    val lab_resource_leak : t
    val leak_after_array_abstraction : t
    val leak_in_footprint : t
    val leak_unknown_origin : t
    val lockless_violation : t
    val lock_consistency_violation : t
    val logging_private_data : t
    val expensive_loop_invariant_call : t
    val memory_leak : t
    val missing_fld : t
    val missing_required_prop : t
    val mixed_self_weakself : t
    val modifies_immutable : t
    val multiple_weakself : t
    val nil_block_call : latent:bool -> t
    val nil_insertion_into_collection : latent:bool -> t
    val nil_messaging_to_non_pod : latent:bool -> t
    val no_match_of_rhs : latent:bool -> t
    val no_matching_case_clause : latent:bool -> t
    val no_matching_function_clause : latent:bool -> t
    val no_true_branch_in_if : latent:bool -> t
    val no_matching_branch_in_try : latent:bool -> t
    val null_argument : latent:bool -> t
    val null_dereference : t
    val nullptr_dereference : latent:bool -> t
    val nullptr_dereference_in_nullsafe_class : latent:bool -> t
    val optional_empty_access : latent:bool -> t
    val precondition_not_found : t
    val precondition_not_met : t
    val premature_nil_termination : t
    val pulse_transitive_access : t
    val pulse_memory_leak_c : t
    val pulse_memory_leak_cpp : t
    val pulse_resource_leak : t
    val pulse_unawaited_awaitable : t
    val pulse_uninitialized_const : t
    val pure_function : t
    val quandary_taint_error : t
    val readonly_shared_ptr_param : t
    val regex_op_on_ui_thread : t
    val resource_leak : t
    val retain_cycle : t
    val scope_leakage : t
    val sensitive_data_flow : t
    val skip_function : t
    val shell_injection : t
    val shell_injection_risk : t
    val sql_injection : t
    val sql_injection_risk : t
    val stack_variable_address_escape : t
    val starvation : t
    val static_initialization_order_fiasco : t
    val strict_mode_violation : t
    val strong_self_not_checked : t
    val symexec_memory_error : t
    val taint_error : t
    val thread_safety_violation : t
    val topl_error : latent:bool -> t
    val uninitialized_value : t
    val uninitialized_value_pulse : latent:bool -> t
    val unnecessary_copy_pulse : t
    val unnecessary_copy_assignment_pulse : t
    val unnecessary_copy_assignment_const_pulse : t
    val unnecessary_copy_assignment_movable_pulse : t
    val unnecessary_copy_intermediate_pulse : t
    val unnecessary_copy_intermediate_const_pulse : t
    val unnecessary_copy_movable_pulse : t
    val unnecessary_copy_optional_pulse : t
    val unnecessary_copy_optional_const_pulse : t
    val unnecessary_copy_return_pulse : t
    val unreachable_code_after : t
    val use_after_delete : latent:bool -> t
    val use_after_free : latent:bool -> t
    val use_after_lifetime : latent:bool -> t
    val untrusted_buffer_access : t
    val untrusted_deserialization : t
    val untrusted_deserialization_risk : t
    val untrusted_file : t
    val untrusted_file_risk : t
    val untrusted_heap_allocation : t
    val untrusted_intent_creation : t
    val untrusted_url_risk : t
    val untrusted_environment_change_risk : t
    val untrusted_variable_length_array : t
    val user_controlled_sql_risk : t
    val vector_invalidation : latent:bool -> t
    val pulse_reference_stability : t
    val weak_self_in_noescape_block : t
    val wrong_argument_number : t
    val unreachable_cost_call : kind:CostKind.t -> t
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    \ No newline at end of file + t

    Create a new issue and register it in the list of all issues. NOTE: if the issue with the same string id is already registered, overrides `hum` but DOES NOT override `enabled`. This trick allows to deal with disabling/enabling dynamic issues from the config, when we don't know all params yet. Thus, the human-readable description can be updated when we encounter the definition of the issue type.

    val checker_can_report : Checker.t -> t -> bool

    Whether the issue was registered as coming from the given checker. Important to call this before reporting to keep documentation accurate.

    val set_enabled : t -> bool -> unit
    val abduction_case_not_implemented : t
    val arbitrary_code_execution_under_lock : t
    val array_of_pointsto : t
    val array_out_of_bounds_l1 : t
    val array_out_of_bounds_l2 : t
    val array_out_of_bounds_l3 : t
    val assert_failure : t
    val bad_footprint : t
    val bad_arg : latent:bool -> t
    val bad_key : latent:bool -> t
    val bad_map : latent:bool -> t
    val bad_record : latent:bool -> t
    val bad_return : latent:bool -> t
    val biabduction_analysis_stops : t
    val biabduction_retain_cycle : t
    val block_parameter_not_null_checked : t
    val buffer_overrun_l1 : t
    val buffer_overrun_l2 : t
    val buffer_overrun_l3 : t
    val buffer_overrun_l4 : t
    val buffer_overrun_l5 : t
    val buffer_overrun_s2 : t
    val buffer_overrun_u5 : t
    val cannot_star : t
    val captured_strong_self : t
    val checkers_allocates_memory : t

    Warning name when a performance critical method directly or indirectly calls a method allocating memory

    val checkers_annotation_reachability_error : t
    val checkers_calls_expensive_method : t

    Warning name when a performance critical method directly or indirectly calls a method annotatd as expensive

    val checkers_expensive_overrides_unexpensive : t

    Warning name for the subtyping rule: method not annotated as expensive cannot be overridden by a method annotated as expensive

    val checkers_fragment_retain_view : t
    val checkers_printf_args : t
    val class_cast_exception : t
    val complexity_increase : kind:CostKind.t -> is_on_ui_thread:bool -> t
    val condition_always_false : t
    val condition_always_true : t
    val config_impact_analysis : t
    val config_impact_analysis_strict : t
    val pulse_config_usage : t
    val pulse_const_refable : t
    val constant_address_dereference : latent:bool -> t
    val cxx_ref_captured_in_block : t
    val create_intent_from_uri : t
    val cross_site_scripting : t
    val dangling_pointer_dereference : t
    val dangling_pointer_dereference_maybe : t
    val data_flow_to_sink : t
    val datalog_fact : t
    val dead_store : t
    val deadlock : t
    val divide_by_zero : t
    val do_not_report : t

    an issue type that should never be reported

    val empty_vector_access : t
    val exposed_insecure_intent_handling : t
    val expensive_cost_call : kind:CostKind.t -> t
    val failure_exe : t
    val guardedby_violation : t
    val impure_function : t
    val inefficient_keyset_iterator : t
    val inferbo_alloc_is_big : t
    val inferbo_alloc_is_negative : t
    val inferbo_alloc_is_zero : t
    val inferbo_alloc_may_be_big : t
    val inferbo_alloc_may_be_negative : t
    val infinite_cost_call : kind:CostKind.t -> t
    val inherently_dangerous_function : t
    val insecure_intent_handling : t
    val integer_overflow_l1 : t
    val integer_overflow_l2 : t
    val integer_overflow_l5 : t
    val integer_overflow_u5 : t
    val interface_not_thread_safe : t
    val internal_error : t
    val invalid_sil : t
    val invariant_call : t
    val ipc_on_ui_thread : t
    val javascript_injection : t
    val lab_resource_leak : t
    val leak_after_array_abstraction : t
    val leak_in_footprint : t
    val leak_unknown_origin : t
    val lockless_violation : t
    val lock_consistency_violation : t
    val logging_private_data : t
    val expensive_loop_invariant_call : t
    val memory_leak : t
    val missing_fld : t
    val missing_required_prop : t
    val mixed_self_weakself : t
    val modifies_immutable : t
    val multiple_weakself : t
    val nil_block_call : latent:bool -> t
    val nil_insertion_into_collection : latent:bool -> t
    val nil_messaging_to_non_pod : latent:bool -> t
    val no_match_of_rhs : latent:bool -> t
    val no_matching_case_clause : latent:bool -> t
    val no_matching_function_clause : latent:bool -> t
    val no_true_branch_in_if : latent:bool -> t
    val no_matching_branch_in_try : latent:bool -> t
    val null_argument : latent:bool -> t
    val null_dereference : t
    val nullptr_dereference : latent:bool -> t
    val nullptr_dereference_in_nullsafe_class : latent:bool -> t
    val optional_empty_access : latent:bool -> t
    val precondition_not_found : t
    val precondition_not_met : t
    val premature_nil_termination : t
    val pulse_dict_missing_key : t
    val pulse_transitive_access : t
    val pulse_memory_leak_c : t
    val pulse_memory_leak_cpp : t
    val pulse_resource_leak : t
    val pulse_unawaited_awaitable : t
    val pulse_uninitialized_const : t
    val pure_function : t
    val quandary_taint_error : t
    val readonly_shared_ptr_param : t
    val regex_op_on_ui_thread : t
    val resource_leak : t
    val retain_cycle : t
    val scope_leakage : t
    val sensitive_data_flow : t
    val skip_function : t
    val shell_injection : t
    val shell_injection_risk : t
    val sql_injection : t
    val sql_injection_risk : t
    val stack_variable_address_escape : t
    val starvation : t
    val static_initialization_order_fiasco : t
    val strict_mode_violation : t
    val strong_self_not_checked : t
    val symexec_memory_error : t
    val taint_error : t
    val thread_safety_violation : t
    val topl_error : latent:bool -> t
    val uninitialized_value : t
    val uninitialized_value_pulse : latent:bool -> t
    val unnecessary_copy_pulse : t
    val unnecessary_copy_assignment_pulse : t
    val unnecessary_copy_assignment_const_pulse : t
    val unnecessary_copy_assignment_movable_pulse : t
    val unnecessary_copy_intermediate_pulse : t
    val unnecessary_copy_intermediate_const_pulse : t
    val unnecessary_copy_movable_pulse : t
    val unnecessary_copy_optional_pulse : t
    val unnecessary_copy_optional_const_pulse : t
    val unnecessary_copy_return_pulse : t
    val unreachable_code_after : t
    val use_after_delete : latent:bool -> t
    val use_after_free : latent:bool -> t
    val use_after_lifetime : latent:bool -> t
    val untrusted_buffer_access : t
    val untrusted_deserialization : t
    val untrusted_deserialization_risk : t
    val untrusted_file : t
    val untrusted_file_risk : t
    val untrusted_heap_allocation : t
    val untrusted_intent_creation : t
    val untrusted_url_risk : t
    val untrusted_environment_change_risk : t
    val untrusted_variable_length_array : t
    val user_controlled_sql_risk : t
    val vector_invalidation : latent:bool -> t
    val pulse_reference_stability : t
    val weak_self_in_noescape_block : t
    val wrong_argument_number : t
    val unreachable_cost_call : kind:CostKind.t -> t
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    \ No newline at end of file diff --git a/odoc/next/infer/IBase/ScubaLogging/index.html b/odoc/next/infer/IBase/ScubaLogging/index.html index 54886f437c1..8b18b27f9b0 100644 --- a/odoc/next/infer/IBase/ScubaLogging/index.html +++ b/odoc/next/infer/IBase/ScubaLogging/index.html @@ -1,3 +1,7 @@ -ScubaLogging (infer.IBase.ScubaLogging)

    Module IBase.ScubaLogging

    Functionality for logging into "infer_events" Scuba table. The table is organized in form of key-value pairs. Two most important fields are "event" and "value". Other fields in the table correspond to things common for this particular run of Infer.

    val log_many : LogEntry.t list -> unit

    Log several events in one go. Useful when you do custom aggregations and have a place to log all aggregated results at once.

    val log_count : label:string -> value:int -> unit

    Log anything that can be counted. Events will be prefixed with "count."

    val log_duration : label:string -> duration_us:int -> unit

    Log elapsed time. Events will be prefixed with "time."

    val log_message : label:string -> message:string -> unit

    Log a string. Event is prefixed with "msg."

    val cost_log_message : label:string -> message:string -> unit

    Similar to log_message, but log only when --cost-scuba-logging option is given.

    val pulse_log_message : label:string -> message:string -> unit

    Similar to log_message, but log only when --pulse-scuba-logging option is given.

    val execute_with_time_logging : string -> (unit -> 'a) -> 'a

    A helper to log execution time of a particular function. Use this to measure a performance of a given function. Example:

    let f a b = <some code>
    +ScubaLogging (infer.IBase.ScubaLogging)

    Module IBase.ScubaLogging

    Functionality for logging into "infer_events" Scuba table. The table is organized in form of key-value pairs. Two most important fields are "event" and "value". Other fields in the table correspond to things common for this particular run of Infer.

    val log_many : LogEntry.t list -> unit

    Log several events in one go. Useful when you do custom aggregations and have a place to log all aggregated results at once.

    val log_count : label:string -> value:int -> unit

    Log anything that can be counted. Events will be prefixed with "count."

    val log_duration : label:string -> duration_us:int -> unit

    Log elapsed time. Events will be prefixed with "time."

    val log_message : label:string -> message:string -> unit

    Log a string. Event is prefixed with "msg."

    val log_message_with_location : + label:string -> + loc:string -> + message:string -> + unit
    val cost_log_message : label:string -> message:string -> unit

    Similar to log_message, but log only when --cost-scuba-logging option is given.

    val pulse_log_message : label:string -> loc:string -> message:string -> unit

    Similar to log_message, but log only when --pulse-scuba-logging option is given.

    val execute_with_time_logging : string -> (unit -> 'a) -> 'a

    A helper to log execution time of a particular function. Use this to measure a performance of a given function. Example:

    let f a b = <some code>
     let f a b = ScubaLogging.execute_with_time_logging "f" (fun () -> f a b)
    val register_global_log_flushing_at_exit : unit -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IR/BUILTINS/module-type-S/index.html b/odoc/next/infer/IR/BUILTINS/module-type-S/index.html index f293277a537..34b5173a61f 100644 --- a/odoc/next/infer/IR/BUILTINS/module-type-S/index.html +++ b/odoc/next/infer/IR/BUILTINS/module-type-S/index.html @@ -1,2 +1,2 @@ -S (infer.IR.BUILTINS.S)

    Module type BUILTINS.S

    List of all builtins that are interpreted specially by the backend

    type t
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    \ No newline at end of file +S (infer.IR.BUILTINS.S)

    Module type BUILTINS.S

    List of all builtins that are interpreted specially by the backend

    type t
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __hack_throw : t
    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    \ No newline at end of file diff --git a/odoc/next/infer/IR/BuiltinDecl/index.html b/odoc/next/infer/IR/BuiltinDecl/index.html index 75510906ed5..dbd6bc9b87a 100644 --- a/odoc/next/infer/IR/BuiltinDecl/index.html +++ b/odoc/next/infer/IR/BuiltinDecl/index.html @@ -1,2 +1,2 @@ -BuiltinDecl (infer.IR.BuiltinDecl)

    Module IR.BuiltinDecl

    Procnames for the builtin functions supported

    include BUILTINS.S with type t = Procname.t
    type t = Procname.t
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    val is_declared : Procname.t -> bool
    val __erlang_equal : Procname.t
    val __erlang_exactly_equal : Procname.t
    val __erlang_not_equal : Procname.t
    val __erlang_exactly_not_equal : Procname.t
    val __erlang_lesser : Procname.t
    val __erlang_lesser_or_equal : Procname.t
    val __erlang_greater : Procname.t
    val __erlang_greater_or_equal : Procname.t
    val __erlang_error_badkey : Procname.t
    val __erlang_error_badmatch : Procname.t
    val __erlang_error_badmap : Procname.t
    val __erlang_error_badrecord : Procname.t
    val __erlang_error_badreturn : Procname.t

    Not a runtime error in Erlang. It means that the actual type disagrees with the spec.

    val __erlang_error_case_clause : Procname.t
    val __erlang_error_function_clause : Procname.t
    val __erlang_error_if_clause : Procname.t
    val __erlang_error_try_clause : Procname.t
    val __erlang_make_atom : Procname.t
    val __erlang_make_integer : Procname.t
    val __erlang_make_cons : Procname.t
    val __erlang_make_nil : Procname.t
    val __erlang_make_tuple : Procname.t
    val __erlang_make_map : Procname.t
    val __erlang_make_str_const : Procname.t
    val __erlang_make_bitstring : Procname.t
    val __erlang_receive : Procname.t
    val __erlang_str_equal : Procname.t
    val __infer_initializer_list : Procname.t
    val __infer_skip_function : Procname.t
    val __infer_skip_gcc_asm_stmt : Procname.t
    val __infer_structured_binding : Procname.t
    val __infer_generic_selection_expr : Procname.t
    val __atomic_fetch_max : Procname.t
    val __atomic_fetch_min : Procname.t
    val __atomic_fetch_nand : Procname.t
    val __atomic_max_fetch : Procname.t
    val __atomic_min_fetch : Procname.t
    val __atomic_nand_fetch : Procname.t
    val __c11_atomic_fetch_max : Procname.t
    val __c11_atomic_fetch_min : Procname.t
    val __call_objc_block : Procname.t
    val __call_c_function_ptr : Procname.t
    val __opencl_atomic_fetch_max : Procname.t
    val __opencl_atomic_fetch_min : Procname.t
    val __builtin_cxx_co_return : Procname.t
    val __builtin_cxx_co_await : Procname.t
    val __get_lazy_class : t

    returns the a LazyClass representation of its arguement (a type name). A LazyClass represents a class that we know the name of but don't necessarily know if the class has been defined somewhere.

    val __lazy_class_initialize : t

    returns the singleton object associated with a given type, and performs lazily its initialization (only generated by the Hack frontend currently)

    val dispatch_sync : Procname.t
    val match_builtin : t -> 'a -> string -> bool
    \ No newline at end of file +BuiltinDecl (infer.IR.BuiltinDecl)

    Module IR.BuiltinDecl

    Procnames for the builtin functions supported

    include BUILTINS.S with type t = Procname.t
    type t = Procname.t
    val __array_access : t
    val __assert_fail : t
    val __builtin_add_overflow : t
    val __builtin_mul_overflow : t
    val __builtin_sub_overflow : t
    val __builtin_va_arg : t
    val __builtin_va_copy : t
    val __builtin_va_end : t
    val __builtin_va_start : t
    val __builtin_offsetof : t
    val __cast : t

    __cast(val,typ) implements java's typ(val)

    val __cxx_typeid : t
    val __delete : t
    val __delete_array : t
    val __delete_locked_attribute : t
    val __exit : t
    val __objc_bridge_transfer : t
    val __get_array_length : t
    val __get_type_of : t
    val __global_access : t
    val __infer_assume : t
    val __infer_fail : t
    val __infer_skip : t

    used to represent behavior that is not modeled in infer

    val __instanceof : t

    __instanceof(val,typ) implements java's val instanceof typ

    val __java_throw : t

    __java_throw implements java's throw instruction (without arg yet, but this is covered by the usage of the return variable during frontend translation

    val __hack_throw : t
    val __method_set_ignore_attribute : t
    val __new : t
    val __new_array : t
    val __objc_alloc_no_fail : t
    val __objc_dictionary_literal : t
    val __objc_get_ref_count : t
    val __objc_set_ref_count : t
    val __placement_delete : t
    val __placement_new : t
    val __print_value : t
    val __require_allocated_array : t
    val __set_array_length : t
    val __set_file_attribute : t
    val __set_locked_attribute : t
    val __set_mem_attribute : t
    val __set_observer_attribute : t
    val __set_unsubscribed_observer_attribute : t
    val __set_wont_leak_attribute : t
    val __split_get_nth : t
    val __throw : t
    val __unwrap_exception : t
    val abort : t
    val exit : t
    val free : t
    val fscanf : t
    val fwscanf : t
    val malloc : t
    val malloc_no_fail : t
    val nsArray_arrayWithObjects : t
    val nsArray_arrayWithObjectsCount : t
    val objc_insert_key : t
    val objc_insert_value : t
    val objc_autorelease_pool_pop : t
    val objc_autorelease_pool_push : t
    val objc_cpp_throw : t
    val pthread_create : t
    val scanf : t
    val sscanf : t
    val swscanf : t
    val vfscanf : t
    val vfwscanf : t
    val vscanf : t
    val vsscanf : t
    val vswscanf : t
    val vwscanf : t
    val wscanf : t
    val zero_initialization : t
    val is_declared : Procname.t -> bool
    val __erlang_equal : Procname.t
    val __erlang_exactly_equal : Procname.t
    val __erlang_not_equal : Procname.t
    val __erlang_exactly_not_equal : Procname.t
    val __erlang_lesser : Procname.t
    val __erlang_lesser_or_equal : Procname.t
    val __erlang_greater : Procname.t
    val __erlang_greater_or_equal : Procname.t
    val __erlang_error_badkey : Procname.t
    val __erlang_error_badmatch : Procname.t
    val __erlang_error_badmap : Procname.t
    val __erlang_error_badrecord : Procname.t
    val __erlang_error_badreturn : Procname.t

    Not a runtime error in Erlang. It means that the actual type disagrees with the spec.

    val __erlang_error_case_clause : Procname.t
    val __erlang_error_function_clause : Procname.t
    val __erlang_error_if_clause : Procname.t
    val __erlang_error_try_clause : Procname.t
    val __erlang_make_atom : Procname.t
    val __erlang_make_integer : Procname.t
    val __erlang_make_cons : Procname.t
    val __erlang_make_nil : Procname.t
    val __erlang_make_tuple : Procname.t
    val __erlang_make_map : Procname.t
    val __erlang_make_str_const : Procname.t
    val __erlang_make_bitstring : Procname.t
    val __erlang_receive : Procname.t
    val __erlang_str_equal : Procname.t
    val __infer_initializer_list : Procname.t
    val __infer_skip_function : Procname.t
    val __infer_skip_gcc_asm_stmt : Procname.t
    val __infer_structured_binding : Procname.t
    val __infer_generic_selection_expr : Procname.t
    val __atomic_fetch_max : Procname.t
    val __atomic_fetch_min : Procname.t
    val __atomic_fetch_nand : Procname.t
    val __atomic_max_fetch : Procname.t
    val __atomic_min_fetch : Procname.t
    val __atomic_nand_fetch : Procname.t
    val __c11_atomic_fetch_max : Procname.t
    val __c11_atomic_fetch_min : Procname.t
    val __call_objc_block : Procname.t
    val __call_c_function_ptr : Procname.t
    val __opencl_atomic_fetch_max : Procname.t
    val __opencl_atomic_fetch_min : Procname.t
    val __builtin_cxx_co_return : Procname.t
    val __builtin_cxx_co_await : Procname.t
    val __get_lazy_class : t

    returns the a LazyClass representation of its arguement (a type name). A LazyClass represents a class that we know the name of but don't necessarily know if the class has been defined somewhere.

    val __lazy_class_initialize : t

    returns the singleton object associated with a given type, and performs lazily its initialization (only generated by the Hack frontend currently)

    val dispatch_sync : Procname.t
    val match_builtin : t -> 'a -> string -> bool
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Fieldname/Set/index.html b/odoc/next/infer/IR/Fieldname/Set/index.html new file mode 100644 index 00000000000..4406cbcaf98 --- /dev/null +++ b/odoc/next/infer/IR/Fieldname/Set/index.html @@ -0,0 +1,2 @@ + +Set (infer.IR.Fieldname.Set)

    Module Fieldname.Set

    Set for fieldnames

    include IStdlib.IStd.Caml.Set.S with type elt = t
    type elt = t
    type t
    val empty : t
    val is_empty : t -> bool
    val mem : elt -> t -> bool
    val add : elt -> t -> t
    val singleton : elt -> t
    val remove : elt -> t -> t
    val union : t -> t -> t
    val inter : t -> t -> t
    val disjoint : t -> t -> bool
    val diff : t -> t -> t
    val compare : t -> t -> int
    val equal : t -> t -> bool
    val subset : t -> t -> bool
    val iter : (elt -> unit) -> t -> unit
    val map : (elt -> elt) -> t -> t
    val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
    val for_all : (elt -> bool) -> t -> bool
    val exists : (elt -> bool) -> t -> bool
    val filter : (elt -> bool) -> t -> t
    val filter_map : (elt -> elt option) -> t -> t
    val partition : (elt -> bool) -> t -> t * t
    val cardinal : t -> int
    val elements : t -> elt list
    val min_elt : t -> elt
    val min_elt_opt : t -> elt option
    val max_elt : t -> elt
    val max_elt_opt : t -> elt option
    val choose : t -> elt
    val choose_opt : t -> elt option
    val split : elt -> t -> t * bool * t
    val find : elt -> t -> elt
    val find_opt : elt -> t -> elt option
    val find_first : (elt -> bool) -> t -> elt
    val find_first_opt : (elt -> bool) -> t -> elt option
    val find_last : (elt -> bool) -> t -> elt
    val find_last_opt : (elt -> bool) -> t -> elt option
    val of_list : elt list -> t
    val to_seq_from : elt -> t -> elt Stdlib.Seq.t
    val to_seq : t -> elt Stdlib.Seq.t
    val to_rev_seq : t -> elt Stdlib.Seq.t
    val add_seq : elt Stdlib.Seq.t -> t -> t
    val of_seq : elt Stdlib.Seq.t -> t
    val is_singleton_or_more : t -> elt IStdlib.IContainer.singleton_or_more
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val pp_element : IStdlib.PrettyPrintable.F.formatter -> elt -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Fieldname/index.html b/odoc/next/infer/IR/Fieldname/index.html index 71dfacfdd25..b35244d44e5 100644 --- a/odoc/next/infer/IR/Fieldname/index.html +++ b/odoc/next/infer/IR/Fieldname/index.html @@ -1,5 +1,5 @@ -Fieldname (infer.IR.Fieldname)

    Module IR.Fieldname

    module F = Stdlib.Format
    type captured_data = {
    1. capture_mode : CapturedVar.capture_mode;
    2. is_weak : bool;
    3. captured_pos : int;
    }
    val compare_captured_data : captured_data -> captured_data -> int
    val equal_captured_data : captured_data -> captured_data -> bool
    val yojson_of_captured_data : +Fieldname (infer.IR.Fieldname)

    Module IR.Fieldname

    module F = Stdlib.Format
    type captured_data = {
    1. capture_mode : CapturedVar.capture_mode;
    2. is_weak : bool;
    }
    val compare_captured_data : captured_data -> captured_data -> int
    val equal_captured_data : captured_data -> captured_data -> bool
    val yojson_of_captured_data : captured_data -> Ppx_yojson_conv_lib.Yojson.Safe.t
    val sexp_of_captured_data : captured_data -> Sexplib0.Sexp.t
    val captured_data_of_sexp : Sexplib0.Sexp.t -> captured_data
    val hash_fold_captured_data : Ppx_hash_lib.Std.Hash.state -> @@ -8,4 +8,4 @@ captured_data option -> captured_data option
    val hash_normalize_captured_data_list : captured_data list -> - captured_data list
    type t

    Names for fields of class/struct/union

    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val yojson_of_t : t -> Ppx_yojson_conv_lib.Yojson.Safe.t
    include Sexplib0.Sexpable.S with type t := t
    val t_of_sexp : Sexplib0__.Sexp.t -> t
    val sexp_of_t : t -> Sexplib0__.Sexp.t
    include Ppx_hash_lib.Hashable.S with type t := t
    val hash_fold_t : t Base__Ppx_hash_lib.hash_fold
    val hash : t -> Base__Ppx_hash_lib.Std.Hash.hash_value
    val hash_normalize : t -> t
    val hash_normalize_opt : t option -> t option
    val hash_normalize_list : t list -> t list
    val compare_name : t -> t -> int

    Similar to compare, but compares only names, except template arguments.

    val make : ?captured_data:captured_data -> Typ.Name.t -> string -> t

    create a field of the given class and fieldname

    val get_class_name : t -> Typ.Name.t
    val get_field_name : t -> string
    val mk_capture_field_in_closure : Mangled.t -> captured_data -> t
    val is_capture_field_in_closure : t -> bool
    val is_weak_capture_field_in_closure : t -> bool
    val is_capture_field_in_closure_by_ref : t -> bool
    val get_capture_field_position : t -> int option
    val is_java : t -> bool
    val is_java_synthetic : t -> bool

    Check if the field is autogenerated/synthetic *

    val is_internal : t -> bool

    Check if the field has the prefix "__" or "_M_" (internal field of std::thread::id)

    module Set : IStdlib.IStd.Caml.Set.S with type elt = t

    Set for fieldnames

    module Map : IStdlib.PrettyPrintable.PPMap with type key = t

    Map for fieldnames

    val is_java_outer_instance : t -> bool

    Check if the field is the synthetic this$n of a nested class, used to access the n-th outer instance.

    val to_string : t -> string

    Convert a field name to a string.

    val to_full_string : t -> string
    val to_simplified_string : t -> string

    Convert a fieldname to a simplified string with at most one-level path. For example,

    • In C++: "<ClassName>::<FieldName>"
    • In Java, ObjC, C#: "<ClassName>.<FieldName>"
    • In C: "<StructName>.<FieldName>" or "<UnionName>.<FieldName>"
    • In Erlang: "<FieldName>"
    val patterns_match : Re.Str.regexp list -> t -> bool

    Test whether a field full string matches to one of the regular expressions.

    val pp : F.formatter -> t -> unit

    Pretty print a field name.

    \ No newline at end of file + captured_data list
    type t

    Names for fields of class/struct/union

    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val yojson_of_t : t -> Ppx_yojson_conv_lib.Yojson.Safe.t
    include Sexplib0.Sexpable.S with type t := t
    val t_of_sexp : Sexplib0__.Sexp.t -> t
    val sexp_of_t : t -> Sexplib0__.Sexp.t
    include Ppx_hash_lib.Hashable.S with type t := t
    val hash_fold_t : t Base__Ppx_hash_lib.hash_fold
    val hash : t -> Base__Ppx_hash_lib.Std.Hash.hash_value
    val hash_normalize : t -> t
    val hash_normalize_opt : t option -> t option
    val hash_normalize_list : t list -> t list
    val compare_name : t -> t -> int

    Similar to compare, but compares only names, except template arguments.

    val make : ?captured_data:captured_data -> Typ.Name.t -> string -> t

    create a field of the given class and fieldname

    val get_class_name : t -> Typ.Name.t
    val get_field_name : t -> string
    val mk_capture_field_in_closure : Mangled.t -> captured_data -> t
    val is_capture_field_in_closure : t -> bool
    val is_weak_capture_field_in_closure : t -> bool
    val is_capture_field_in_closure_by_ref : t -> bool
    val is_java : t -> bool
    val is_java_synthetic : t -> bool

    Check if the field is autogenerated/synthetic *

    val is_internal : t -> bool

    Check if the field has the prefix "__" or "_M_" (internal field of std::thread::id)

    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t

    Set for fieldnames

    module Map : IStdlib.PrettyPrintable.PPMap with type key = t

    Map for fieldnames

    val is_java_outer_instance : t -> bool

    Check if the field is the synthetic this$n of a nested class, used to access the n-th outer instance.

    val to_string : t -> string

    Convert a field name to a string.

    val to_full_string : t -> string
    val to_simplified_string : t -> string

    Convert a fieldname to a simplified string with at most one-level path. For example,

    • In C++: "<ClassName>::<FieldName>"
    • In Java, ObjC, C#: "<ClassName>.<FieldName>"
    • In C: "<StructName>.<FieldName>" or "<UnionName>.<FieldName>"
    • In Erlang: "<FieldName>"
    val patterns_match : Re.Str.regexp list -> t -> bool

    Test whether a field full string matches to one of the regular expressions.

    val pp : F.formatter -> t -> unit

    Pretty print a field name.

    \ No newline at end of file diff --git a/odoc/next/infer/IR/Instrs/index.html b/odoc/next/infer/IR/Instrs/index.html index 4f3fbaafcf5..cfbef6e9faf 100644 --- a/odoc/next/infer/IR/Instrs/index.html +++ b/odoc/next/infer/IR/Instrs/index.html @@ -1,5 +1,5 @@ -Instrs (infer.IR.Instrs)

    Module IR.Instrs

    Manipulate possibly-reversed lists of instructions efficiently

    type reversed
    type not_reversed
    type _ t
    type not_reversed_t = not_reversed t

    defined for convenience: we can write Instrs.not_reversed_t in other modules instead of Instrs.not_reversed Instrs.t

    val empty : _ t
    val singleton : Sil.instr -> _ t
    val append_list : not_reversed t -> Sil.instr list -> not_reversed t
    val of_list : Sil.instr list -> not_reversed t
    val filter_map : +Instrs (infer.IR.Instrs)

    Module IR.Instrs

    Manipulate possibly-reversed lists of instructions efficiently

    type reversed
    type not_reversed
    type _ t
    type not_reversed_t = not_reversed t

    defined for convenience: we can write Instrs.not_reversed_t in other modules instead of Instrs.not_reversed Instrs.t

    val empty : _ t
    val singleton : Sil.instr -> _ t
    val append_list : not_reversed t -> Sil.instr list -> not_reversed t
    val prepend_list : not_reversed t -> Sil.instr list -> not_reversed t
    val of_list : Sil.instr list -> not_reversed t
    val filter_map : not_reversed t -> f:(Sil.instr -> Sil.instr option) -> not_reversed t

    replace every instruction instr with f instr. Preserve physical equality. *

    val map_and_fold : diff --git a/odoc/next/infer/IR/Procdesc/Node/index.html b/odoc/next/infer/IR/Procdesc/Node/index.html index 7e50c9a1992..16f8641603c 100644 --- a/odoc/next/infer/IR/Procdesc/Node/index.html +++ b/odoc/next/infer/IR/Procdesc/Node/index.html @@ -2,4 +2,4 @@ Node (infer.IR.Procdesc.Node)

    Module Procdesc.Node

    node of the control flow graph

    type t

    type of nodes

    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_hash_lib.Hashable.S with type t := t
    val hash_fold_t : t Base__Ppx_hash_lib.hash_fold
    val hash : t -> Base__Ppx_hash_lib.Std.Hash.hash_value
    type id = private int

    node id

    val compare_id : id -> id -> int
    val equal_id : id -> id -> bool
    val hash_fold_id : Ppx_hash_lib.Std.Hash.state -> id -> - Ppx_hash_lib.Std.Hash.state
    val hash_id : id -> Ppx_hash_lib.Std.Hash.hash_value
    type destruction_kind =
    1. | DestrBreakStmt
    2. | DestrContinueStmt
    3. | DestrFields
    4. | DestrReturnStmt
    5. | DestrScope
    6. | DestrTemporariesCleanup
    7. | DestrVirtualBase
    type stmt_nodekind =
    1. | AssertionFailure
    2. | AtomicCompareExchangeBranch
    3. | AtomicExpr
    4. | BetweenJoinAndExit
    5. | BinaryConditionalStmtInit
    6. | BinaryOperatorStmt of string
    7. | Call of string
    8. | CallObjCNew
    9. | CaseStmt
    10. | ClassCastException
    11. | CompoundStmt
    12. | ConditionalStmtBranch
    13. | ConstructorInit
    14. | CXXDynamicCast
    15. | CXXNewExpr
    16. | CXXStdInitializerListExpr
    17. | CXXTemporaryMarkerSet
    18. | CXXTry
    19. | CXXTypeidExpr
    20. | DeclStmt
    21. | DefineBody
    22. | Destruction of destruction_kind
    23. | Erlang
    24. | ErlangCaseClause
    25. | ErlangExpression
    26. | ExceptionHandler
    27. | ExceptionsSink
    28. | ExprWithCleanups
    29. | FinallyBranch
    30. | GCCAsmStmt
    31. | GenericSelectionExpr
    32. | IfStmtBranch
    33. | InitializeDynamicArrayLength
    34. | InitListExp
    35. | LoopBody
    36. | LoopIterIncr
    37. | LoopIterInit
    38. | MessageCall of string
    39. | MethodBody
    40. | MonitorEnter
    41. | MonitorExit
    42. | ObjCCPPThrow
    43. | ObjCIndirectCopyRestoreExpr
    44. | OutOfBound
    45. | ReturnStmt
    46. | Scope of string
    47. | Skip
    48. | SwitchStmt
    49. | ThisNotNull
    50. | Throw
    51. | ThrowNPE
    52. | UnaryOperator

    kind of statement node

    type prune_node_kind =
    1. | PruneNodeKind_ExceptionHandler
    2. | PruneNodeKind_FalseBranch
    3. | PruneNodeKind_InBound
    4. | PruneNodeKind_IsInstance
    5. | PruneNodeKind_MethodBody
    6. | PruneNodeKind_NotNull
    7. | PruneNodeKind_TrueBranch
    type nodekind =
    1. | Start_node
    2. | Exit_node
    3. | Stmt_node of stmt_nodekind
    4. | Join_node
    5. | Prune_node of bool * Sil.if_kind * prune_node_kind
      (*

      (true/false branch, if_kind, comment)

      *)
    6. | Skip_node of string

    kind of cfg node

    val compare_nodekind : nodekind -> nodekind -> int
    val equal_nodekind : nodekind -> nodekind -> bool
    val exn_handler_kind : nodekind

    kind of Stmt_node for an exception handler.

    val exn_sink_kind : nodekind

    kind of Stmt_node for an exceptions sink.

    val throw_kind : nodekind

    kind of Stmt_node for a throw instruction.

    val append_instrs : t -> Sil.instr list -> unit

    Append the instructions to the list of instructions to execute

    val d_instrs : highlight:Sil.instr option -> t -> unit

    Dump instructions for the node, highlighting the given subinstruction if present

    val dummy : Procname.t -> t

    Create a dummy node

    val equal : t -> t -> bool

    Check if two nodes are equal

    val get_description : IStdlib.Pp.env -> t -> string

    Return a description of the node

    val get_distance_to_exit : t -> int option

    Get the distance to the exit node, if it has been computed

    val get_exn : t -> t list

    Get the exception nodes from the current node

    val get_id : t -> id

    Get the unique id of the node

    val get_instrs : t -> Instrs.not_reversed_t

    Get the instructions to be executed

    val get_kind : t -> nodekind

    Get the kind of the current node

    val get_last_loc : t -> IBase.Location.t

    Get the source location of the last instruction in the node

    val find_in_node_or_preds : t -> f:(t -> Sil.instr -> 'a option) -> 'a option

    Find in the given node or its predecessors

    val get_loc : t -> IBase.Location.t

    Get the source location of the node

    val get_preds : t -> t list

    Get the predecessor nodes of the current node

    val get_siblings : t -> t IStdlib.IStd.Sequence.t

    Get siblings of the current node

    val get_proc_name : t -> Procname.t

    Get the name of the procedure the node belongs to

    val get_succs : t -> t list

    Get the successor nodes of the current node

    val get_wto_index : t -> int
    val set_code_block_exit : t -> code_block_exit:t -> unit

    Set an exit node corresponding to a start node of a code block. Using this, when there is a code block, frontend can keep the correspondence between start/exit nodes of a code block.

    val is_dangling : t -> bool

    Returns true if the node is dangling, i.e. no successors and predecessors

    val pp : Stdlib.Format.formatter -> t -> unit

    Pretty print the node

    val pp_id : Stdlib.Format.formatter -> id -> unit

    Pretty print a node id

    val pp_stmt : Stdlib.Format.formatter -> stmt_nodekind -> unit
    val pp_with_instrs : ?print_types:bool -> Stdlib.Format.formatter -> t -> unit

    Pretty print the node with instructions

    val compute_key : t -> NodeKey.t
    \ No newline at end of file + Ppx_hash_lib.Std.Hash.state
    val hash_id : id -> Ppx_hash_lib.Std.Hash.hash_value
    type destruction_kind =
    1. | DestrBreakStmt
    2. | DestrContinueStmt
    3. | DestrFields
    4. | DestrReturnStmt
    5. | DestrScope
    6. | DestrTemporariesCleanup
    7. | DestrVirtualBase
    type stmt_nodekind =
    1. | AssertionFailure
    2. | AtomicCompareExchangeBranch
    3. | AtomicExpr
    4. | BetweenJoinAndExit
    5. | BinaryConditionalStmtInit
    6. | BinaryOperatorStmt of string
    7. | Call of string
    8. | CallObjCNew
    9. | CaseStmt
    10. | ClassCastException
    11. | CompoundStmt
    12. | ConditionalStmtBranch
    13. | ConstructorInit
    14. | CXXDynamicCast
    15. | CXXNewExpr
    16. | CXXStdInitializerListExpr
    17. | CXXTemporaryMarkerSet
    18. | CXXTry
    19. | CXXTypeidExpr
    20. | DeclStmt
    21. | DefineBody
    22. | Destruction of destruction_kind
    23. | Erlang
    24. | ErlangCaseClause
    25. | ErlangExpression
    26. | ExceptionHandler
    27. | ExceptionsSink
    28. | ExprWithCleanups
    29. | FinallyBranch
    30. | GCCAsmStmt
    31. | GenericSelectionExpr
    32. | IfStmtBranch
    33. | InitializeDynamicArrayLength
    34. | InitListExp
    35. | LoopBody
    36. | LoopIterIncr
    37. | LoopIterInit
    38. | MessageCall of string
    39. | MethodBody
    40. | MonitorEnter
    41. | MonitorExit
    42. | ObjCCPPThrow
    43. | ObjCIndirectCopyRestoreExpr
    44. | OutOfBound
    45. | ReturnStmt
    46. | Scope of string
    47. | Skip
    48. | SwitchStmt
    49. | ThisNotNull
    50. | Throw
    51. | ThrowNPE
    52. | UnaryOperator

    kind of statement node

    type prune_node_kind =
    1. | PruneNodeKind_ExceptionHandler
    2. | PruneNodeKind_FalseBranch
    3. | PruneNodeKind_InBound
    4. | PruneNodeKind_IsInstance
    5. | PruneNodeKind_MethodBody
    6. | PruneNodeKind_NotNull
    7. | PruneNodeKind_TrueBranch
    type nodekind =
    1. | Start_node
    2. | Exit_node
    3. | Stmt_node of stmt_nodekind
    4. | Join_node
    5. | Prune_node of bool * Sil.if_kind * prune_node_kind
      (*

      (true/false branch, if_kind, comment)

      *)
    6. | Skip_node of string

    kind of cfg node

    val compare_nodekind : nodekind -> nodekind -> int
    val equal_nodekind : nodekind -> nodekind -> bool
    val exn_handler_kind : nodekind

    kind of Stmt_node for an exception handler.

    val exn_sink_kind : nodekind

    kind of Stmt_node for an exceptions sink.

    val throw_kind : nodekind

    kind of Stmt_node for a throw instruction.

    val append_instrs : t -> Sil.instr list -> unit

    Append the instructions to the list of instructions to execute

    val prepend_instrs : t -> Sil.instr list -> unit

    Prepend the instructions to the list of instructions to execute

    val d_instrs : highlight:Sil.instr option -> t -> unit

    Dump instructions for the node, highlighting the given subinstruction if present

    val dummy : Procname.t -> t

    Create a dummy node

    val equal : t -> t -> bool

    Check if two nodes are equal

    val get_description : IStdlib.Pp.env -> t -> string

    Return a description of the node

    val get_distance_to_exit : t -> int option

    Get the distance to the exit node, if it has been computed

    val get_exn : t -> t list

    Get the exception nodes from the current node

    val get_id : t -> id

    Get the unique id of the node

    val get_instrs : t -> Instrs.not_reversed_t

    Get the instructions to be executed

    val get_kind : t -> nodekind

    Get the kind of the current node

    val get_last_loc : t -> IBase.Location.t

    Get the source location of the last instruction in the node

    val find_in_node_or_preds : t -> f:(t -> Sil.instr -> 'a option) -> 'a option

    Find in the given node or its predecessors

    val get_loc : t -> IBase.Location.t

    Get the source location of the node

    val get_preds : t -> t list

    Get the predecessor nodes of the current node

    val get_siblings : t -> t IStdlib.IStd.Sequence.t

    Get siblings of the current node

    val get_proc_name : t -> Procname.t

    Get the name of the procedure the node belongs to

    val get_succs : t -> t list

    Get the successor nodes of the current node

    val get_wto_index : t -> int
    val set_code_block_exit : t -> code_block_exit:t -> unit

    Set an exit node corresponding to a start node of a code block. Using this, when there is a code block, frontend can keep the correspondence between start/exit nodes of a code block.

    val is_dangling : t -> bool

    Returns true if the node is dangling, i.e. no successors and predecessors

    val pp : Stdlib.Format.formatter -> t -> unit

    Pretty print the node

    val pp_id : Stdlib.Format.formatter -> id -> unit

    Pretty print a node id

    val pp_stmt : Stdlib.Format.formatter -> stmt_nodekind -> unit
    val pp_with_instrs : ?print_types:bool -> Stdlib.Format.formatter -> t -> unit

    Pretty print the node with instructions

    val compute_key : t -> NodeKey.t
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Procname/index.html b/odoc/next/infer/IR/Procname/index.html index c79e8a60d24..83adae88e13 100644 --- a/odoc/next/infer/IR/Procname/index.html +++ b/odoc/next/infer/IR/Procname/index.html @@ -19,4 +19,4 @@ class_name:PythonClassName.t option -> function_name:string -> arity:int option -> - t

    Create a Python procedure name.

    val empty_block : t

    Empty block name.

    val get_language : t -> IBase.Language.t

    Return the language of the procedure.

    val get_method : t -> string

    Return the method/function of a procname.

    val is_objc_block : t -> bool

    Return whether the procname is a block procname.

    val is_cpp_lambda : t -> bool

    Return whether the procname is a cpp lambda procname.

    val is_objc_dealloc : t -> bool

    Return whether the dealloc method of an Objective-C class.

    val is_objc_init : t -> bool

    Return whether the init method of an Objective-C class.

    val is_c_method : t -> bool

    Return true this is an Objective-C/C++ method name.

    val is_clang : t -> bool

    Return true this is an Objective-C/C++ method name or a C function.

    val is_constructor : t -> bool

    Check if this is a constructor.

    val is_csharp : t -> bool

    Check if this is a CSharp procedure name.

    val is_hack : t -> bool

    Check if this is a Hack procedure name.

    val is_java : t -> bool

    Check if this is a Java procedure name.

    val is_python : t -> bool

    Check if this is a Python procedure name.

    val as_java_exn : explanation:string -> t -> Java.t

    Converts to a Java.t. Throws if is_java is false

    val objc_cpp_replace_method_name : t -> string -> t
    val is_infer_undefined : t -> bool

    Check if this is a special Infer undefined procedure.

    val is_static : t -> bool option

    Check if a procedure is a static class method or not. If the procedure is not a class method or is unknown to be static, it returns None. For now, this checking does not work on C++ methods.

    val get_global_name_of_initializer : t -> string option

    Return the name of the global for which this procedure is the initializer if this is an initializer, None otherwise.

    val pp_without_templates : Stdlib.Format.formatter -> t -> unit

    Pretty print a c++ proc name for the user to see.

    val pp : Stdlib.Format.formatter -> t -> unit

    Pretty print a proc name for the user to see.

    val pp_verbose : Stdlib.Format.formatter -> t -> unit

    Pretty print a proc name for the user to see with verbosity parameter.

    val to_string : ?verbosity:detail_level -> t -> string

    Convert a proc name into a string for the user to see.

    val describe : Stdlib.Format.formatter -> t -> unit

    to use in user messages

    val replace_class : t -> ?arity_incr:int -> Typ.Name.t -> t

    Replace the class name component of a procedure name. In case of Java, replace package and class name.

    val is_method_in_objc_protocol : t -> bool
    val pp_simplified_string : ?withclass:bool -> F.formatter -> t -> unit

    Pretty print a proc name as an easy string for the user to see in an IDE.

    val to_simplified_string : ?withclass:bool -> t -> string

    Convert a proc name into an easy string for the user to see in an IDE.

    val from_string_c_fun : string -> t

    Convert a string to a c function name.

    val replace_java_inner_class_prefix_regex : string -> string

    Replace "$[0-9]+" index into "$_" in Java proc name.

    val hashable_name : t -> string

    Convert the procedure name in a format suitable for computing the bug hash.

    val pp_unique_id : F.formatter -> t -> unit

    Print a proc name as a unique identifier.

    val to_unique_id : t -> string

    Convert a proc name into a unique identifier.

    val to_short_unique_name : t -> string

    Convert a proc name into a unique identfier guaranteed to be short (less than 50 characters)

    val to_filename : t -> string

    Convert a proc name to a filename.

    val get_qualifiers : t -> QualifiedCppName.t

    get qualifiers of C/objc/C++ method/function

    val decr_hack_arity : t -> t option

    return a Hack procname with decremented arity. Return None if input has no arity or 0 arity

    val get_hack_arity : t -> int option

    get the arity of a Hack procname

    val get_hack_static_init : HackClassName.t -> t

    get the sinit procname in Hack

    val pp_name_only : F.formatter -> t -> unit

    Print name of procedure with at most one-level path. For example,

    • In C++: "<ClassName>::<ProcName>"
    • In Java, ObjC, C#: "<ClassName>.<ProcName>"
    • In C/Erlang: "<ProcName>"
    val is_c : t -> bool
    val is_lambda_name : string -> bool
    val is_lambda : t -> bool
    val is_lambda_or_block : t -> bool
    val patterns_match : Re.Str.regexp list -> t -> bool

    Test whether a proc name matches to one of the regular expressions.

    val is_erlang_unsupported : t -> bool
    val is_erlang : t -> bool
    val erlang_call_unqualified : arity:int -> t

    A special infer-erlang procname that represents a syntactic erlang (unqualified) function call. arity is the arity of the erlang function. First parameter of this procedure is expecteed to be the erlang function name, and the remaining parameters are the erlang parameters (given one-by-one and not as an erlang list).

    val erlang_call_qualified : arity:int -> t

    Same as erlang_call_unqualified but is expected to have an erlang module name as the first parameter, and the function name as second. arity is (still) the erlang arity of the function.

    val is_erlang_call_unqualified : t -> bool
    val is_erlang_call_qualified : t -> bool
    val is_hack_builtins : t -> bool
    val is_hack_sinit : t -> bool
    val is_hack_init : t -> bool
    val has_hack_classname : t -> bool
    val is_hack_async_name : t -> bool
    \ No newline at end of file + t

    Create a Python procedure name.

    val empty_block : t

    Empty block name.

    val get_language : t -> IBase.Language.t

    Return the language of the procedure.

    val get_method : t -> string

    Return the method/function of a procname.

    val is_objc_block : t -> bool

    Return whether the procname is a block procname.

    val is_cpp_lambda : t -> bool

    Return whether the procname is a cpp lambda procname.

    val is_objc_dealloc : t -> bool

    Return whether the dealloc method of an Objective-C class.

    val is_objc_init : t -> bool

    Return whether the init method of an Objective-C class.

    val is_c_method : t -> bool

    Return true this is an Objective-C/C++ method name.

    val is_clang : t -> bool

    Return true this is an Objective-C/C++ method name or a C function.

    val is_constructor : t -> bool

    Check if this is a constructor.

    val is_csharp : t -> bool

    Check if this is a CSharp procedure name.

    val is_hack : t -> bool

    Check if this is a Hack procedure name.

    val is_java : t -> bool

    Check if this is a Java procedure name.

    val is_python : t -> bool

    Check if this is a Python procedure name.

    val as_java_exn : explanation:string -> t -> Java.t

    Converts to a Java.t. Throws if is_java is false

    val objc_cpp_replace_method_name : t -> string -> t
    val is_infer_undefined : t -> bool

    Check if this is a special Infer undefined procedure.

    val is_static : t -> bool option

    Check if a procedure is a static class method or not. If the procedure is not a class method or is unknown to be static, it returns None. For now, this checking does not work on C++ methods.

    val get_global_name_of_initializer : t -> string option

    Return the name of the global for which this procedure is the initializer if this is an initializer, None otherwise.

    val pp_without_templates : Stdlib.Format.formatter -> t -> unit

    Pretty print a c++ proc name for the user to see.

    val pp : Stdlib.Format.formatter -> t -> unit

    Pretty print a proc name for the user to see.

    val pp_verbose : Stdlib.Format.formatter -> t -> unit

    Pretty print a proc name for the user to see with verbosity parameter.

    val to_string : ?verbosity:detail_level -> t -> string

    Convert a proc name into a string for the user to see.

    val describe : Stdlib.Format.formatter -> t -> unit

    to use in user messages

    val replace_class : t -> ?arity_incr:int -> Typ.Name.t -> t

    Replace the class name component of a procedure name. In case of Java, replace package and class name.

    val is_method_in_objc_protocol : t -> bool
    val pp_simplified_string : ?withclass:bool -> F.formatter -> t -> unit

    Pretty print a proc name as an easy string for the user to see in an IDE.

    val to_simplified_string : ?withclass:bool -> t -> string

    Convert a proc name into an easy string for the user to see in an IDE.

    val from_string_c_fun : string -> t

    Convert a string to a c function name.

    val replace_java_inner_class_prefix_regex : string -> string

    Replace "$[0-9]+" index into "$_" in Java proc name.

    val hashable_name : t -> string

    Convert the procedure name in a format suitable for computing the bug hash.

    val pp_unique_id : F.formatter -> t -> unit

    Print a proc name as a unique identifier.

    val to_unique_id : t -> string

    Convert a proc name into a unique identifier.

    val to_short_unique_name : t -> string

    Convert a proc name into a unique identfier guaranteed to be short (less than 50 characters)

    val to_filename : t -> string

    Convert a proc name to a filename.

    val get_qualifiers : t -> QualifiedCppName.t

    get qualifiers of C/objc/C++ method/function

    val decr_hack_arity : t -> t option

    return a Hack procname with decremented arity. Return None if input has no arity or 0 arity

    val get_hack_arity : t -> int option

    get the arity of a Hack procname

    val get_hack_static_init : is_trait:bool -> HackClassName.t -> t

    get the sinit procname in Hack

    val pp_name_only : F.formatter -> t -> unit

    Print name of procedure with at most one-level path. For example,

    • In C++: "<ClassName>::<ProcName>"
    • In Java, ObjC, C#: "<ClassName>.<ProcName>"
    • In C/Erlang: "<ProcName>"
    val is_c : t -> bool
    val is_lambda_name : string -> bool
    val is_lambda : t -> bool
    val is_lambda_or_block : t -> bool
    val patterns_match : Re.Str.regexp list -> t -> bool

    Test whether a proc name matches to one of the regular expressions.

    val is_erlang_unsupported : t -> bool
    val is_erlang : t -> bool
    val erlang_call_unqualified : arity:int -> t

    A special infer-erlang procname that represents a syntactic erlang (unqualified) function call. arity is the arity of the erlang function. First parameter of this procedure is expecteed to be the erlang function name, and the remaining parameters are the erlang parameters (given one-by-one and not as an erlang list).

    val erlang_call_qualified : arity:int -> t

    Same as erlang_call_unqualified but is expected to have an erlang module name as the first parameter, and the function name as second. arity is (still) the erlang arity of the function.

    val is_erlang_call_unqualified : t -> bool
    val is_erlang_call_qualified : t -> bool
    val is_hack_builtins : t -> bool
    val is_hack_sinit : t -> bool
    val has_hack_classname : t -> bool
    val is_hack_async_name : t -> bool
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/HeapPath/Set/index.html b/odoc/next/infer/IR/Specialization/HeapPath/Set/index.html new file mode 100644 index 00000000000..ed607aa0dac --- /dev/null +++ b/odoc/next/infer/IR/Specialization/HeapPath/Set/index.html @@ -0,0 +1,2 @@ + +Set (infer.IR.Specialization.HeapPath.Set)

    Module HeapPath.Set

    include IStdlib.IStd.Caml.Set.S with type elt = t
    type elt = t
    type t
    val empty : t
    val is_empty : t -> bool
    val mem : elt -> t -> bool
    val add : elt -> t -> t
    val singleton : elt -> t
    val remove : elt -> t -> t
    val union : t -> t -> t
    val inter : t -> t -> t
    val disjoint : t -> t -> bool
    val diff : t -> t -> t
    val compare : t -> t -> int
    val equal : t -> t -> bool
    val subset : t -> t -> bool
    val iter : (elt -> unit) -> t -> unit
    val map : (elt -> elt) -> t -> t
    val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
    val for_all : (elt -> bool) -> t -> bool
    val exists : (elt -> bool) -> t -> bool
    val filter : (elt -> bool) -> t -> t
    val filter_map : (elt -> elt option) -> t -> t
    val partition : (elt -> bool) -> t -> t * t
    val cardinal : t -> int
    val elements : t -> elt list
    val min_elt : t -> elt
    val min_elt_opt : t -> elt option
    val max_elt : t -> elt
    val max_elt_opt : t -> elt option
    val choose : t -> elt
    val choose_opt : t -> elt option
    val split : elt -> t -> t * bool * t
    val find : elt -> t -> elt
    val find_opt : elt -> t -> elt option
    val find_first : (elt -> bool) -> t -> elt
    val find_first_opt : (elt -> bool) -> t -> elt option
    val find_last : (elt -> bool) -> t -> elt
    val find_last_opt : (elt -> bool) -> t -> elt option
    val of_list : elt list -> t
    val to_seq_from : elt -> t -> elt Stdlib.Seq.t
    val to_seq : t -> elt Stdlib.Seq.t
    val to_rev_seq : t -> elt Stdlib.Seq.t
    val add_seq : elt Stdlib.Seq.t -> t -> t
    val of_seq : elt Stdlib.Seq.t -> t
    val is_singleton_or_more : t -> elt IStdlib.IContainer.singleton_or_more
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val pp_element : IStdlib.PrettyPrintable.F.formatter -> elt -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/HeapPath/index.html b/odoc/next/infer/IR/Specialization/HeapPath/index.html index e3a159ef209..f8c387385e7 100644 --- a/odoc/next/infer/IR/Specialization/HeapPath/index.html +++ b/odoc/next/infer/IR/Specialization/HeapPath/index.html @@ -1,2 +1,2 @@ -HeapPath (infer.IR.Specialization.HeapPath)

    Module Specialization.HeapPath

    type t =
    1. | Pvar of Pvar.t
    2. | FieldAccess of Fieldname.t * t
    3. | Dereference of t
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val pp : F.formatter -> t -> unit
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    \ No newline at end of file +HeapPath (infer.IR.Specialization.HeapPath)

    Module Specialization.HeapPath

    type t =
    1. | Pvar of Pvar.t
    2. | FieldAccess of Fieldname.t * t
    3. | Dereference of t
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val pp : F.formatter -> t -> unit
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/Pulse/Aliases/index.html b/odoc/next/infer/IR/Specialization/Pulse/Aliases/index.html index ed0a6335755..c7aca275e5f 100644 --- a/odoc/next/infer/IR/Specialization/Pulse/Aliases/index.html +++ b/odoc/next/infer/IR/Specialization/Pulse/Aliases/index.html @@ -1,2 +1,2 @@ -Aliases (infer.IR.Specialization.Pulse.Aliases)

    Module Pulse.Aliases

    type t = Pvar.t list list

    set of alias sets (Note: list is enough because it is normalised during construction)

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    \ No newline at end of file +Aliases (infer.IR.Specialization.Pulse.Aliases)

    Module Pulse.Aliases

    type t = HeapPath.t list list

    set of alias sets (Note: list is enough because it is normalised during construction)

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/Set/index.html b/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/Set/index.html deleted file mode 100644 index 711994d3631..00000000000 --- a/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/Set/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Set (infer.IR.Specialization.Pulse.DynamicTypes.Set)

    Module DynamicTypes.Set

    include IStdlib.IStd.Caml.Set.S with type elt = t
    type elt = t
    type t
    val empty : t
    val is_empty : t -> bool
    val mem : elt -> t -> bool
    val add : elt -> t -> t
    val singleton : elt -> t
    val remove : elt -> t -> t
    val union : t -> t -> t
    val inter : t -> t -> t
    val disjoint : t -> t -> bool
    val diff : t -> t -> t
    val compare : t -> t -> int
    val equal : t -> t -> bool
    val subset : t -> t -> bool
    val iter : (elt -> unit) -> t -> unit
    val map : (elt -> elt) -> t -> t
    val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
    val for_all : (elt -> bool) -> t -> bool
    val exists : (elt -> bool) -> t -> bool
    val filter : (elt -> bool) -> t -> t
    val filter_map : (elt -> elt option) -> t -> t
    val partition : (elt -> bool) -> t -> t * t
    val cardinal : t -> int
    val elements : t -> elt list
    val min_elt : t -> elt
    val min_elt_opt : t -> elt option
    val max_elt : t -> elt
    val max_elt_opt : t -> elt option
    val choose : t -> elt
    val choose_opt : t -> elt option
    val split : elt -> t -> t * bool * t
    val find : elt -> t -> elt
    val find_opt : elt -> t -> elt option
    val find_first : (elt -> bool) -> t -> elt
    val find_first_opt : (elt -> bool) -> t -> elt option
    val find_last : (elt -> bool) -> t -> elt
    val find_last_opt : (elt -> bool) -> t -> elt option
    val of_list : elt list -> t
    val to_seq_from : elt -> t -> elt Stdlib.Seq.t
    val to_seq : t -> elt Stdlib.Seq.t
    val to_rev_seq : t -> elt Stdlib.Seq.t
    val add_seq : elt Stdlib.Seq.t -> t -> t
    val of_seq : elt Stdlib.Seq.t -> t
    val is_singleton_or_more : t -> elt IStdlib.IContainer.singleton_or_more
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val pp_element : IStdlib.PrettyPrintable.F.formatter -> elt -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/index.html b/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/index.html index a8e5037d8b0..95df58beb6c 100644 --- a/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/index.html +++ b/odoc/next/infer/IR/Specialization/Pulse/DynamicTypes/index.html @@ -1,2 +1,2 @@ -DynamicTypes (infer.IR.Specialization.Pulse.DynamicTypes)

    Module Pulse.DynamicTypes

    binding from heap paths to their inferred dynamic type (will be used for devirtualization in the callee)

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t
    \ No newline at end of file +DynamicTypes (infer.IR.Specialization.Pulse.DynamicTypes)

    Module Pulse.DynamicTypes

    binding from heap paths to their inferred dynamic type (will be used for devirtualization in the callee)

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/Pulse/Set/index.html b/odoc/next/infer/IR/Specialization/Pulse/Set/index.html new file mode 100644 index 00000000000..8003a8ec1d6 --- /dev/null +++ b/odoc/next/infer/IR/Specialization/Pulse/Set/index.html @@ -0,0 +1,2 @@ + +Set (infer.IR.Specialization.Pulse.Set)

    Module Pulse.Set

    include IStdlib.IStd.Caml.Set.S with type elt = t
    type elt = t
    type t
    val empty : t
    val is_empty : t -> bool
    val mem : elt -> t -> bool
    val add : elt -> t -> t
    val singleton : elt -> t
    val remove : elt -> t -> t
    val union : t -> t -> t
    val inter : t -> t -> t
    val disjoint : t -> t -> bool
    val diff : t -> t -> t
    val compare : t -> t -> int
    val equal : t -> t -> bool
    val subset : t -> t -> bool
    val iter : (elt -> unit) -> t -> unit
    val map : (elt -> elt) -> t -> t
    val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
    val for_all : (elt -> bool) -> t -> bool
    val exists : (elt -> bool) -> t -> bool
    val filter : (elt -> bool) -> t -> t
    val filter_map : (elt -> elt option) -> t -> t
    val partition : (elt -> bool) -> t -> t * t
    val cardinal : t -> int
    val elements : t -> elt list
    val min_elt : t -> elt
    val min_elt_opt : t -> elt option
    val max_elt : t -> elt
    val max_elt_opt : t -> elt option
    val choose : t -> elt
    val choose_opt : t -> elt option
    val split : elt -> t -> t * bool * t
    val find : elt -> t -> elt
    val find_opt : elt -> t -> elt option
    val find_first : (elt -> bool) -> t -> elt
    val find_first_opt : (elt -> bool) -> t -> elt option
    val find_last : (elt -> bool) -> t -> elt
    val find_last_opt : (elt -> bool) -> t -> elt option
    val of_list : elt list -> t
    val to_seq_from : elt -> t -> elt Stdlib.Seq.t
    val to_seq : t -> elt Stdlib.Seq.t
    val to_rev_seq : t -> elt Stdlib.Seq.t
    val add_seq : elt Stdlib.Seq.t -> t -> t
    val of_seq : elt Stdlib.Seq.t -> t
    val is_singleton_or_more : t -> elt IStdlib.IContainer.singleton_or_more
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val pp_element : IStdlib.PrettyPrintable.F.formatter -> elt -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Specialization/Pulse/index.html b/odoc/next/infer/IR/Specialization/Pulse/index.html index 0433c9f1e33..fcb73f96ef7 100644 --- a/odoc/next/infer/IR/Specialization/Pulse/index.html +++ b/odoc/next/infer/IR/Specialization/Pulse/index.html @@ -1,2 +1,2 @@ -Pulse (infer.IR.Specialization.Pulse)

    Module Specialization.Pulse

    module Aliases : sig ... end
    module DynamicTypes : sig ... end
    type t =
    1. | Aliases of Aliases.t
    2. | DynamicTypes of DynamicTypes.t
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val pp : F.formatter -> t -> unit
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    val is_pulse_specialization_limit_not_reached : 'a Map.t -> bool
    \ No newline at end of file +Pulse (infer.IR.Specialization.Pulse)

    Module Specialization.Pulse

    module Aliases : sig ... end
    module DynamicTypes : sig ... end
    type t = {
    1. aliases : Aliases.t option;
    2. dynamic_types : DynamicTypes.t;
    }

    currently aliases=None means we did not detect any alias when applying the previous summary and this specialization will not introduce any alias assumption.

    aliases=Some [] means something went wrong... We have detected some aliases when applying the last summary, but we were not able to phrase it in term of parameters equalities.

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val bottom : t
    val is_empty : t -> bool
    val pp : F.formatter -> t -> unit
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t
    val is_pulse_specialization_limit_not_reached : 'a Map.t -> bool
    \ No newline at end of file diff --git a/odoc/next/infer/IR/Tenv/index.html b/odoc/next/infer/IR/Tenv/index.html index 8b3d623ff56..daf9c9b8d79 100644 --- a/odoc/next/infer/IR/Tenv/index.html +++ b/odoc/next/infer/IR/Tenv/index.html @@ -37,4 +37,4 @@ t -> Typ.Name.t -> Fieldname.t -> - Struct.field_info option

    resolve_field_info tenv class_name field tries to find the first field declaration that matches field name (ignoring its enclosing declared type), starting from class class_name.

    val resolve_fieldname : t -> Typ.Name.t -> string -> Fieldname.t option

    Similar to resolve_field_info, but returns the resolved field name.

    val find_cpp_destructor : t -> Typ.Name.t -> Procname.t option
    val find_cpp_constructor : t -> Typ.Name.t -> Procname.t list
    val is_trivially_copyable : t -> Typ.t -> bool
    val normalize : per_file -> per_file

    Produce an equivalent type environment that has maximal sharing between its structures.

    \ No newline at end of file + Struct.field_info option

    resolve_field_info tenv class_name field tries to find the first field declaration that matches field name (ignoring its enclosing declared type), starting from class class_name.

    val resolve_fieldname : t -> Typ.Name.t -> string -> Fieldname.t option

    Similar to resolve_field_info, but returns the resolved field name.

    val find_cpp_destructor : t -> Typ.Name.t -> Procname.t option
    val find_cpp_constructor : t -> Typ.Name.t -> Procname.t list
    val is_trivially_copyable : t -> Typ.t -> bool
    val get_hack_direct_used_traits : t -> Typ.Name.t -> HackClassName.t list
    val normalize : per_file -> per_file

    Produce an equivalent type environment that has maximal sharing between its structures.

    \ No newline at end of file diff --git a/odoc/next/infer/IR/Typ/Name/index.html b/odoc/next/infer/IR/Typ/Name/index.html index f062390ebdf..87aa9fdca3a 100644 --- a/odoc/next/infer/IR/Typ/Name/index.html +++ b/odoc/next/infer/IR/Typ/Name/index.html @@ -1,2 +1,2 @@ -Name (infer.IR.Typ.Name)

    Module Typ.Name

    type t = name

    Named types.

    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val yojson_of_t : t -> Ppx_yojson_conv_lib.Yojson.Safe.t
    include Sexplib0.Sexpable.S with type t := t
    val t_of_sexp : Sexplib0__.Sexp.t -> t
    val sexp_of_t : t -> Sexplib0__.Sexp.t
    include Ppx_hash_lib.Hashable.S with type t := t
    val hash_fold_t : t Base__Ppx_hash_lib.hash_fold
    val hash_normalize : t -> t
    val hash_normalize_opt : t option -> t option
    val hash_normalize_list : t list -> t list
    val compare_name : t -> t -> int

    Similar to compare, but compares only names, except template arguments.

    val equal : t -> t -> bool

    Equality for typenames

    val hash : t -> int
    val to_string : t -> string

    convert the typename to a string

    val pp : Stdlib.Format.formatter -> t -> unit
    val is_class : t -> bool

    is_class name holds if name names CPP/Objc/Java class

    val is_union : t -> bool

    is_union name holds if name names C/CPP union

    val is_same_type : t -> t -> bool

    is_class name1 name2 holds if name1 and name2 name same kind of type

    val name_without_templates : t -> string

    name of the c++ typename without qualifier

    val name : t -> string

    name of the typename without qualifier

    val qual_name : t -> QualifiedCppName.t

    qualified name of the type, may return nonsense for Java classes

    val unqualified_name : t -> QualifiedCppName.t
    val get_template_spec_info : t -> template_spec_info option
    val is_objc_protocol : t -> bool
    val is_objc_class : t -> bool
    val is_hack_class : t -> bool
    val is_python_class : t -> bool
    module C : sig ... end
    module CSharp : sig ... end
    module Hack : sig ... end
    module Java : sig ... end
    module Cpp : sig ... end
    module Objc : sig ... end
    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    module Hash : IStdlib.IStd.Caml.Hashtbl.S with type key = t
    \ No newline at end of file +Name (infer.IR.Typ.Name)

    Module Typ.Name

    type t = name

    Named types.

    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val yojson_of_t : t -> Ppx_yojson_conv_lib.Yojson.Safe.t
    include Sexplib0.Sexpable.S with type t := t
    val t_of_sexp : Sexplib0__.Sexp.t -> t
    val sexp_of_t : t -> Sexplib0__.Sexp.t
    include Ppx_hash_lib.Hashable.S with type t := t
    val hash_fold_t : t Base__Ppx_hash_lib.hash_fold
    val hash_normalize : t -> t
    val hash_normalize_opt : t option -> t option
    val hash_normalize_list : t list -> t list
    val compare_name : t -> t -> int

    Similar to compare, but compares only names, except template arguments.

    val equal : t -> t -> bool

    Equality for typenames

    val hash : t -> int
    val to_string : t -> string

    convert the typename to a string

    val pp : Stdlib.Format.formatter -> t -> unit
    val is_class : t -> bool

    is_class name holds if name names CPP/Objc/Java class

    val is_union : t -> bool

    is_union name holds if name names C/CPP union

    val is_same_type : t -> t -> bool

    is_class name1 name2 holds if name1 and name2 name same kind of type

    val name_without_templates : t -> string

    name of the c++ typename without qualifier

    val name : t -> string

    name of the typename without qualifier

    val qual_name : t -> QualifiedCppName.t

    qualified name of the type, may return nonsense for Java classes

    val unqualified_name : t -> QualifiedCppName.t
    val get_template_spec_info : t -> template_spec_info option
    val is_objc_protocol : t -> bool
    val is_objc_class : t -> bool
    val is_objc_block : t -> bool
    val is_hack_class : t -> bool
    val is_python_class : t -> bool
    module C : sig ... end
    module CSharp : sig ... end
    module Hack : sig ... end
    module Java : sig ... end
    module Cpp : sig ... end
    module Objc : sig ... end
    module Set : IStdlib.PrettyPrintable.PPSet with type elt = t
    module Map : IStdlib.PrettyPrintable.PPMap with type key = t
    module Hash : IStdlib.IStd.Caml.Hashtbl.S with type key = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAbductiveDomain/AddressAttributes/index.html b/odoc/next/infer/Pulselib/PulseAbductiveDomain/AddressAttributes/index.html index f8cb11d0432..1b61a20108e 100644 --- a/odoc/next/infer/Pulselib/PulseAbductiveDomain/AddressAttributes/index.html +++ b/odoc/next/infer/Pulselib/PulseAbductiveDomain/AddressAttributes/index.html @@ -72,7 +72,22 @@ t
    val is_csharp_resource_released : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> - bool
    val add_dynamic_type : + bool
    val add_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val remove_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val is_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + bool
    val remove_taint_attrs : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> t
    val is_ref_counted : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> bool
    val get_closure_proc_name : diff --git a/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Attributes/index.html b/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Attributes/index.html index 7320837eb0c..07c383878d9 100644 --- a/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Attributes/index.html +++ b/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Attributes/index.html @@ -62,7 +62,16 @@ t -> (Pulselib.PulseBasicInterface.Timestamp.t * Pulselib.PulseBasicInterface.Trace.t) - option
    val add_dynamic_type : + option
    val add_dict_contain_const_keys : t -> t -> t
    val remove_dict_contain_const_keys : t -> t -> t
    val is_dict_contain_const_keys : t -> t -> bool
    val add_dict_read_const_key : + Pulselib.PulseBasicInterface.Timestamp.t -> + Pulselib.PulseBasicInterface.Trace.t -> + t -> + IR.Fieldname.t -> + t -> + t
    val get_dict_read_const_keys : + t -> + t -> + Pulselib.PulseBasicInterface.Attribute.ConstKeys.t option
    val add_dynamic_type : Pulselib.PulseBasicInterface.Attribute.dynamic_type_data -> t -> t -> diff --git a/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Memory/Access/index.html b/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Memory/Access/index.html index e129e358a18..2acc8244602 100644 --- a/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Memory/Access/index.html +++ b/odoc/next/infer/Pulselib/PulseAbductiveDomain/CanonValue/Memory/Access/index.html @@ -1,6 +1,6 @@ Access (infer.Pulselib.PulseAbductiveDomain.CanonValue.Memory.Access)

    Module Memory.Access

    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType - with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAbductiveDomain/Summary/index.html b/odoc/next/infer/Pulselib/PulseAbductiveDomain/Summary/index.html index c5d4aca8c8c..8d20301c5eb 100644 --- a/odoc/next/infer/Pulselib/PulseAbductiveDomain/Summary/index.html +++ b/odoc/next/infer/Pulselib/PulseAbductiveDomain/Summary/index.html @@ -23,13 +23,6 @@ * IR.CSharpClassName.t * Pulselib.PulseBasicInterface.Trace.t * IBase.Location.t - | `RetainCycle of - summary - * t - * Pulselib.PulseBasicInterface.Trace.t list - * DecompilerExpr.t - * DecompilerExpr.t - * IBase.Location.t | `MemoryLeak of summary * t diff --git a/odoc/next/infer/Pulselib/PulseAbductiveDomain/index.html b/odoc/next/infer/Pulselib/PulseAbductiveDomain/index.html index 476a323166a..3eec747da4c 100644 --- a/odoc/next/infer/Pulselib/PulseAbductiveDomain/index.html +++ b/odoc/next/infer/Pulselib/PulseAbductiveDomain/index.html @@ -1,9 +1,5 @@ -PulseAbductiveDomain (infer.Pulselib.PulseAbductiveDomain)

    Module Pulselib.PulseAbductiveDomain

    module F = Stdlib.Format
    module BaseDomain = PulseBaseDomain
    module Decompiler = PulseDecompiler
    module DecompilerExpr = PulseDecompilerExpr
    module PathContext = PulsePathContext

    Abductive, value-normalizing layer on top of BaseDomain

    The operations in this module take care of two things that are important for the safety of domain operations:

    1. Propagate operations on the current state to the pre-condition when necessary. This is the "abductive" part of the domain and follows the principles of biabduction as laid out in *Compositional Shape Analysis by Means of Bi-Abduction*, JACM, 2011, https://doi.org/10.1145/2049697.2049700. Simply put, a read from a memory location that is reachable from the precondition for the first time is taken to mean that this memory location had better been allocated since the beginning of the function for the operation to be safe, hence we "abduce" that this was the case and add it to the pre-condition (unless we already know that address to be invalid of course).

    2. Normalize values (AbstractValue.t) in and out of the state according to their canonical representatives as per the current path condition. The idea is that one can ask about any abstract value and functions in this API will normalize it as needed first before querying the abstract state, and normalize any value found in the abstract state as needed too. For example, values in the raw map corresponding to the memory are not necessarily normalized at all times but the API allows one to pretend they are by normalizing them on the fly. On the other hand, *keys* in the memory map are always normalized so values must be normalized before being looked up in the map and this module takes care of that transparently too. See also PulseCanonValue.

    module type BaseDomainSig = sig ... end

    signature common to the "normal" Domain, representing the post at the current program point, and the inverted PreDomain, representing the inferred pre-condition

    The post abstract state at each program point, or current state.

    The inferred pre-condition at each program point, biabduction style.

    type t = private {
    1. post : PostDomain.t;
      (*

      state at the current program point

      *)
    2. pre : PreDomain.t;
      (*

      inferred procedure pre-condition leading to the current program point

      *)
    3. path_condition : Pulselib.PulseBasicInterface.Formula.t;
      (*

      arithmetic facts true along the path (holding for both pre and post since abstract values are immutable)

      *)
    4. decompiler : Decompiler.t;
    5. topl : PulseTopl.state;
      (*

      state at of the Topl monitor at the current program point, when Topl is enabled

      *)
    6. need_dynamic_type_specialization : Pulselib.PulseBasicInterface.AbstractValue.Set.t;
      (*

      a set of abstract values that are used as receiver of method calls in the instructions reached so far

      *)
    7. transitive_info : Pulselib.PulseBasicInterface.TransitiveInfo.t;
      (*

      record transitive information inter-procedurally

      *)
    8. skipped_calls : Pulselib.PulseBasicInterface.SkippedCalls.t;
      (*

      metadata: procedure calls for which no summary was found

      *)
    }

    pre/post on a single program path

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val leq : lhs:t -> rhs:t -> bool
    val pp : Stdlib.Format.formatter -> t -> unit
    val mk_initial : - IR.Tenv.t -> - IR.ProcAttributes.t -> - IR.Specialization.Pulse.t option -> - t
    module Stack : sig ... end

    Safe version of PulseBaseStack

    module Memory : sig ... end

    Safe version of PulseBaseMemory

    module AddressAttributes : sig ... end
    val should_havoc_if_unknown : +PulseAbductiveDomain (infer.Pulselib.PulseAbductiveDomain)

    Module Pulselib.PulseAbductiveDomain

    module F = Stdlib.Format
    module BaseDomain = PulseBaseDomain
    module Decompiler = PulseDecompiler
    module DecompilerExpr = PulseDecompilerExpr
    module PathContext = PulsePathContext

    Abductive, value-normalizing layer on top of BaseDomain

    The operations in this module take care of two things that are important for the safety of domain operations:

    1. Propagate operations on the current state to the pre-condition when necessary. This is the "abductive" part of the domain and follows the principles of biabduction as laid out in *Compositional Shape Analysis by Means of Bi-Abduction*, JACM, 2011, https://doi.org/10.1145/2049697.2049700. Simply put, a read from a memory location that is reachable from the precondition for the first time is taken to mean that this memory location had better been allocated since the beginning of the function for the operation to be safe, hence we "abduce" that this was the case and add it to the pre-condition (unless we already know that address to be invalid of course).

    2. Normalize values (AbstractValue.t) in and out of the state according to their canonical representatives as per the current path condition. The idea is that one can ask about any abstract value and functions in this API will normalize it as needed first before querying the abstract state, and normalize any value found in the abstract state as needed too. For example, values in the raw map corresponding to the memory are not necessarily normalized at all times but the API allows one to pretend they are by normalizing them on the fly. On the other hand, *keys* in the memory map are always normalized so values must be normalized before being looked up in the map and this module takes care of that transparently too. See also PulseCanonValue.

    module type BaseDomainSig = sig ... end

    signature common to the "normal" Domain, representing the post at the current program point, and the inverted PreDomain, representing the inferred pre-condition

    The post abstract state at each program point, or current state.

    The inferred pre-condition at each program point, biabduction style.

    type t = private {
    1. post : PostDomain.t;
      (*

      state at the current program point

      *)
    2. pre : PreDomain.t;
      (*

      inferred procedure pre-condition leading to the current program point

      *)
    3. path_condition : Pulselib.PulseBasicInterface.Formula.t;
      (*

      arithmetic facts true along the path (holding for both pre and post since abstract values are immutable)

      *)
    4. decompiler : Decompiler.t;
    5. topl : PulseTopl.state;
      (*

      state at of the Topl monitor at the current program point, when Topl is enabled

      *)
    6. need_dynamic_type_specialization : Pulselib.PulseBasicInterface.AbstractValue.Set.t;
      (*

      a set of abstract values that are used as receiver of method calls in the instructions reached so far

      *)
    7. transitive_info : Pulselib.PulseBasicInterface.TransitiveInfo.t;
      (*

      record transitive information inter-procedurally

      *)
    8. skipped_calls : Pulselib.PulseBasicInterface.SkippedCalls.t;
      (*

      metadata: procedure calls for which no summary was found

      *)
    }

    pre/post on a single program path

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val leq : lhs:t -> rhs:t -> bool
    val pp : Stdlib.Format.formatter -> t -> unit
    val mk_initial : IR.Tenv.t -> IR.ProcAttributes.t -> t
    module Stack : sig ... end

    Safe version of PulseBaseStack

    module Memory : sig ... end

    Safe version of PulseBaseMemory

    module AddressAttributes : sig ... end
    val should_havoc_if_unknown : unit -> [> `ShouldHavoc | `ShouldOnlyHavocResources ]
    val apply_unknown_effect : ?havoc_filter: @@ -43,7 +39,11 @@ t
    val add_need_dynamic_type_specialization : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> - t
    val map_decompiler : t -> f:(Decompiler.t -> Decompiler.t) -> t
    val set_post_edges : + t
    val map_decompiler : t -> f:(Decompiler.t -> Decompiler.t) -> t
    val add_block_source : + Pulselib.PulseBasicInterface.AbstractValue.t -> + string -> + t -> + t
    val set_post_edges : Pulselib.PulseBasicInterface.AbstractValue.t -> PulseBaseMemory.Edges.t -> t -> diff --git a/odoc/next/infer/Pulselib/PulseAccess/index.html b/odoc/next/infer/Pulselib/PulseAccess/index.html index 86cb5153539..a90b31c48e9 100644 --- a/odoc/next/infer/Pulselib/PulseAccess/index.html +++ b/odoc/next/infer/Pulselib/PulseAccess/index.html @@ -1,7 +1,7 @@ PulseAccess (infer.Pulselib.PulseAccess)

    Module Pulselib.PulseAccess

    module type S = sig ... end
    include S with type key := PulseAbstractValue.t
    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType with type t = PulseAbstractValue.t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType - with type t = Pulselib.PulseAbstractValue.t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = Pulselib.PulseAbstractValue.t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAccess/module-type-S/index.html b/odoc/next/infer/Pulselib/PulseAccess/module-type-S/index.html index 506ed8cb648..9ea468bd2a6 100644 --- a/odoc/next/infer/Pulselib/PulseAccess/module-type-S/index.html +++ b/odoc/next/infer/Pulselib/PulseAccess/module-type-S/index.html @@ -1,7 +1,7 @@ S (infer.Pulselib.PulseAccess.S)

    Module type PulseAccess.S

    type key
    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType with type t = key Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType - with type t = key Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = key Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAccessResult/index.html b/odoc/next/infer/Pulselib/PulseAccessResult/index.html index 35ed719e99c..96d8c191463 100644 --- a/odoc/next/infer/Pulselib/PulseAccessResult/index.html +++ b/odoc/next/infer/Pulselib/PulseAccessResult/index.html @@ -45,13 +45,6 @@ * IR.CSharpClassName.t * Pulselib.PulseBasicInterface.Trace.t * IBase.Location.t - | `RetainCycle of - AbductiveDomain.Summary.t - * AbductiveDomain.t - * Pulselib.PulseBasicInterface.Trace.t list - * DecompilerExpr.t - * DecompilerExpr.t - * IBase.Location.t | abductive_summary_error ]) IStdlib.IStd.result -> (AbductiveDomain.Summary.t, [> abductive_summary_error ]) IStdlib.IStd.result
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAliasSpecialization/index.html b/odoc/next/infer/Pulselib/PulseAliasSpecialization/index.html deleted file mode 100644 index 94c85c37087..00000000000 --- a/odoc/next/infer/Pulselib/PulseAliasSpecialization/index.html +++ /dev/null @@ -1,12 +0,0 @@ - -PulseAliasSpecialization (infer.Pulselib.PulseAliasSpecialization)

    Module Pulselib.PulseAliasSpecialization

    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAttribute/Attributes/index.html b/odoc/next/infer/Pulselib/PulseAttribute/Attributes/index.html index a442cf086b3..5500c7a3572 100644 --- a/odoc/next/infer/Pulselib/PulseAttribute/Attributes/index.html +++ b/odoc/next/infer/Pulselib/PulseAttribute/Attributes/index.html @@ -9,7 +9,7 @@ t -> (IR.Procname.t * IBase.Location.t * Trace.t) option
    val get_copied_into : t -> CopiedInto.t option
    val get_copied_return : t -> - (AbstractValue.t * bool * CopyOrigin.t * IBase.Location.t) option
    val remove_copied_return : t -> t
    val get_source_origin_of_copy : t -> (PulseAbstractValue.t * bool) option
    val get_allocation : t -> (allocator * Trace.t) option
    val remove_allocation : t -> t
    val get_unknown_effect : t -> (CallEvent.t * ValueHistory.t) option
    val get_dynamic_type : t -> dynamic_type_data option
    val get_static_type : t -> IR.Typ.Name.t option
    val is_java_resource_released : t -> bool
    val is_csharp_resource_released : t -> bool
    val is_end_of_collection : t -> bool
    val get_invalid : t -> (Invalidation.t * Trace.t) option
    val get_tainted : t -> TaintedSet.t
    val remove_tainted : t -> t
    val remove_must_not_be_tainted : ?kinds:TaintConfig.Kind.Set.t -> t -> t
    val get_propagate_taint_from : + (AbstractValue.t * bool * CopyOrigin.t * IBase.Location.t) option
    val remove_copied_return : t -> t
    val get_source_origin_of_copy : t -> (PulseAbstractValue.t * bool) option
    val get_allocation : t -> (allocator * Trace.t) option
    val remove_allocation : t -> t
    val get_unknown_effect : t -> (CallEvent.t * ValueHistory.t) option
    val remove_dict_contain_const_keys : t -> t
    val is_dict_contain_const_keys : t -> bool
    val get_dict_read_const_keys : t -> ConstKeys.t option
    val get_dynamic_type : t -> dynamic_type_data option
    val get_static_type : t -> IR.Typ.Name.t option
    val is_java_resource_released : t -> bool
    val is_csharp_resource_released : t -> bool
    val is_end_of_collection : t -> bool
    val get_invalid : t -> (Invalidation.t * Trace.t) option
    val get_tainted : t -> TaintedSet.t
    val remove_tainted : t -> t
    val remove_must_not_be_tainted : ?kinds:TaintConfig.Kind.Set.t -> t -> t
    val get_propagate_taint_from : t -> (taint_propagation_reason * taint_in list) option
    val remove_propagate_taint_from : t -> t
    val get_returned_from_unknown : t -> AbstractValue.t list option
    val get_taint_sanitized : t -> TaintSanitizedSet.t
    val remove_taint_sanitized : t -> t
    val get_must_be_valid : t -> diff --git a/odoc/next/infer/Pulselib/PulseAttribute/ConstKeys/index.html b/odoc/next/infer/Pulselib/PulseAttribute/ConstKeys/index.html new file mode 100644 index 00000000000..070b48ad4c5 --- /dev/null +++ b/odoc/next/infer/Pulselib/PulseAttribute/ConstKeys/index.html @@ -0,0 +1,6 @@ + +ConstKeys (infer.Pulselib.PulseAttribute.ConstKeys)

    Module PulseAttribute.ConstKeys

    type t
    val singleton : IR.Fieldname.t -> (Timestamp.t * Trace.t) -> t
    val fold : + (IR.Fieldname.t -> (Timestamp.t * Trace.t) -> 'a -> 'a) -> + t -> + 'a -> + 'a
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAttribute/UninitializedTyp/index.html b/odoc/next/infer/Pulselib/PulseAttribute/UninitializedTyp/index.html index d81dc7d684f..de917779cb1 100644 --- a/odoc/next/infer/Pulselib/PulseAttribute/UninitializedTyp/index.html +++ b/odoc/next/infer/Pulselib/PulseAttribute/UninitializedTyp/index.html @@ -1,2 +1,2 @@ -UninitializedTyp (infer.Pulselib.PulseAttribute.UninitializedTyp)

    Module PulseAttribute.UninitializedTyp

    type t =
    1. | Value
    2. | Const of IR.Fieldname.t
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    \ No newline at end of file +UninitializedTyp (infer.Pulselib.PulseAttribute.UninitializedTyp)

    Module PulseAttribute.UninitializedTyp

    type t =
    1. | Value
    2. | Const of IR.Fieldname.t
    3. | DictMissingKey of {
      1. dict : DecompilerExpr.t;
      2. key : IR.Fieldname.t;
      }
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseAttribute/index.html b/odoc/next/infer/Pulselib/PulseAttribute/index.html index 540906ff8bf..0f884e2c0fb 100644 --- a/odoc/next/infer/Pulselib/PulseAttribute/index.html +++ b/odoc/next/infer/Pulselib/PulseAttribute/index.html @@ -4,7 +4,7 @@ IStdlib.PrettyPrintable.PPSet with type elt = TaintSanitized.t
    type taint_propagation_reason =
    1. | InternalModel
    2. | UnknownCall
    3. | UserConfig
    val pp_taint_propagation_reason : F.formatter -> taint_propagation_reason -> - unit
    module CopyOrigin : sig ... end
    module CopiedInto : sig ... end
    module ConfigUsage : sig ... end
    module UninitializedTyp : sig ... end
    type dynamic_type_data = {
    1. typ : IR.Typ.t;
    2. source_file : IBase.SourceFile.t option;
    }
    val compare_dynamic_type_data : dynamic_type_data -> dynamic_type_data -> int
    val equal_dynamic_type_data : dynamic_type_data -> dynamic_type_data -> bool
    type t =
    1. | AddressOfCppTemporary of IR.Var.t * ValueHistory.t
    2. | AddressOfStackVariable of IR.Var.t * IBase.Location.t * ValueHistory.t
    3. | Allocated of allocator * Trace.t
    4. | AlwaysReachable
    5. | Closure of IR.Procname.t
    6. | ConfigUsage of ConfigUsage.t
    7. | ConstString of string
    8. | CopiedInto of CopiedInto.t
      (*

      records the copied var/field for each source address

      *)
    9. | CopiedReturn of {
      1. source : AbstractValue.t;
      2. is_const_ref : bool;
      3. from : CopyOrigin.t;
      4. copied_location : IBase.Location.t;
      }
      (*

      records the copied value for the return address

      *)
    10. | DynamicType of dynamic_type_data
    11. | EndOfCollection
    12. | Initialized
    13. | Invalid of Invalidation.t * Trace.t
    14. | LastLookup of AbstractValue.t
    15. | MustBeInitialized of Timestamp.t * Trace.t
    16. | MustBeValid of Timestamp.t * Trace.t * Invalidation.must_be_valid_reason option
    17. | MustNotBeTainted of TaintSink.t TaintSinkMap.t
    18. | JavaResourceReleased
    19. | CSharpResourceReleased
    20. | HackAsyncAwaited
    21. | PropagateTaintFrom of taint_propagation_reason * taint_in list
    22. | ReturnedFromUnknown of AbstractValue.t list
    23. | SourceOriginOfCopy of {
      1. source : PulseAbstractValue.t;
      2. is_const_ref : bool;
      }
      (*

      records the source value for a given copy to lookup the appropriate heap in non-disj domain

      *)
    24. | StaticType of IR.Typ.Name.t
      (*

      type gotten or inferred from types in SIL instructions (only for Hack frontend)

      *)
    25. | StdMoved
    26. | StdVectorReserve
    27. | Tainted of TaintedSet.t
    28. | TaintSanitized of TaintSanitizedSet.t
    29. | Uninitialized of UninitializedTyp.t
    30. | UnknownEffect of CallEvent.t * ValueHistory.t
      (*

      generated by calls to unknown functions to remember that a pointer has been passed to an unknown function and so everything reachable from it has potentially been affected in unknown ways

      *)
    31. | UnreachableAt of IBase.Location.t
      (*

      temporary marker to remember where a variable became unreachable; helps with accurately reporting leaks

      *)
    32. | UsedAsBranchCond of IR.Procname.t * IBase.Location.t * Trace.t
    33. | WrittenTo of Timestamp.t * Trace.t
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val pp : F.formatter -> t -> unit
    val filter_unreachable : + unit
    module CopyOrigin : sig ... end
    module CopiedInto : sig ... end
    module ConfigUsage : sig ... end
    module UninitializedTyp : sig ... end
    type dynamic_type_data = {
    1. typ : IR.Typ.t;
    2. source_file : IBase.SourceFile.t option;
    }
    val compare_dynamic_type_data : dynamic_type_data -> dynamic_type_data -> int
    val equal_dynamic_type_data : dynamic_type_data -> dynamic_type_data -> bool
    module ConstKeys : sig ... end
    type t =
    1. | AddressOfCppTemporary of IR.Var.t * ValueHistory.t
    2. | AddressOfStackVariable of IR.Var.t * IBase.Location.t * ValueHistory.t
    3. | Allocated of allocator * Trace.t
    4. | AlwaysReachable
    5. | Closure of IR.Procname.t
    6. | ConfigUsage of ConfigUsage.t
    7. | ConstString of string
    8. | CopiedInto of CopiedInto.t
      (*

      records the copied var/field for each source address

      *)
    9. | CopiedReturn of {
      1. source : AbstractValue.t;
      2. is_const_ref : bool;
      3. from : CopyOrigin.t;
      4. copied_location : IBase.Location.t;
      }
      (*

      records the copied value for the return address

      *)
    10. | DictContainConstKeys
      (*

      the dictionary contains only constant keys (note: only string constant is supported for now)

      *)
    11. | DictReadConstKeys of ConstKeys.t
      (*

      constant string keys that are read from the dictionary

      *)
    12. | DynamicType of dynamic_type_data
    13. | EndOfCollection
    14. | Initialized
    15. | Invalid of Invalidation.t * Trace.t
    16. | LastLookup of AbstractValue.t
    17. | MustBeInitialized of Timestamp.t * Trace.t
    18. | MustBeValid of Timestamp.t * Trace.t * Invalidation.must_be_valid_reason option
    19. | MustNotBeTainted of TaintSink.t TaintSinkMap.t
    20. | JavaResourceReleased
    21. | CSharpResourceReleased
    22. | HackAsyncAwaited
    23. | PropagateTaintFrom of taint_propagation_reason * taint_in list
    24. | ReturnedFromUnknown of AbstractValue.t list
    25. | SourceOriginOfCopy of {
      1. source : PulseAbstractValue.t;
      2. is_const_ref : bool;
      }
      (*

      records the source value for a given copy to lookup the appropriate heap in non-disj domain

      *)
    26. | StaticType of IR.Typ.Name.t
      (*

      type gotten or inferred from types in SIL instructions (only for Hack frontend)

      *)
    27. | StdMoved
    28. | StdVectorReserve
    29. | Tainted of TaintedSet.t
    30. | TaintSanitized of TaintSanitizedSet.t
    31. | Uninitialized of UninitializedTyp.t
    32. | UnknownEffect of CallEvent.t * ValueHistory.t
      (*

      generated by calls to unknown functions to remember that a pointer has been passed to an unknown function and so everything reachable from it has potentially been affected in unknown ways

      *)
    33. | UnreachableAt of IBase.Location.t
      (*

      temporary marker to remember where a variable became unreachable; helps with accurately reporting leaks

      *)
    34. | UsedAsBranchCond of IR.Procname.t * IBase.Location.t * Trace.t
    35. | WrittenTo of Timestamp.t * Trace.t
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    val pp : F.formatter -> t -> unit
    val filter_unreachable : AbstractValue.Set.t AbstractValue.Map.t -> (AbstractValue.t -> bool) -> t -> diff --git a/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/index.html b/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/index.html index b826afad3df..87b806c063b 100644 --- a/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/index.html +++ b/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/index.html @@ -97,7 +97,25 @@ t -> (Pulselib.PulseBasicInterface.Timestamp.t * Pulselib.PulseBasicInterface.Trace.t) - option
    val add_dynamic_type : + option
    val add_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val remove_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val is_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + bool
    val add_dynamic_type : Pulselib.PulseBasicInterface.Attribute.dynamic_type_data -> Pulselib.PulseBasicInterface.AbstractValue.t -> t -> diff --git a/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/module-type-S/index.html b/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/module-type-S/index.html index 8a863f53bce..e1b33ad2be8 100644 --- a/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/module-type-S/index.html +++ b/odoc/next/infer/Pulselib/PulseBaseAddressAttributes/module-type-S/index.html @@ -65,7 +65,16 @@ t -> (Pulselib.PulseBasicInterface.Timestamp.t * Pulselib.PulseBasicInterface.Trace.t) - option
    val add_dynamic_type : + option
    val add_dict_contain_const_keys : key -> t -> t
    val remove_dict_contain_const_keys : key -> t -> t
    val is_dict_contain_const_keys : key -> t -> bool
    val get_dict_read_const_keys : + key -> + t -> + Pulselib.PulseBasicInterface.Attribute.ConstKeys.t option
    val add_dynamic_type : Pulselib.PulseBasicInterface.Attribute.dynamic_type_data -> key -> t -> diff --git a/odoc/next/infer/Pulselib/PulseBaseMemory/Access/index.html b/odoc/next/infer/Pulselib/PulseBaseMemory/Access/index.html index 32b8de02bb2..23870292591 100644 --- a/odoc/next/infer/Pulselib/PulseBaseMemory/Access/index.html +++ b/odoc/next/infer/Pulselib/PulseBaseMemory/Access/index.html @@ -2,7 +2,7 @@ Access (infer.Pulselib.PulseBaseMemory.Access)

    Module PulseBaseMemory.Access

    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType with type t = PulseBasicInterface.AbstractValue.t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = - Pulselib.PulseBasicInterface.AbstractValue.t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + Pulselib.PulseBasicInterface.AbstractValue.t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseBaseMemory/module-type-S/Access/index.html b/odoc/next/infer/Pulselib/PulseBaseMemory/module-type-S/Access/index.html index 9fb64b359d2..edd5bbc71da 100644 --- a/odoc/next/infer/Pulselib/PulseBaseMemory/module-type-S/Access/index.html +++ b/odoc/next/infer/Pulselib/PulseBaseMemory/module-type-S/Access/index.html @@ -1,7 +1,7 @@ Access (infer.Pulselib.PulseBaseMemory.S.Access)

    Module S.Access

    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType with type t = key Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType - with type t = key Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = key Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseCanonValue/Make/Attributes/index.html b/odoc/next/infer/Pulselib/PulseCanonValue/Make/Attributes/index.html index 6461c4f57bf..8991b6b9672 100644 --- a/odoc/next/infer/Pulselib/PulseCanonValue/Make/Attributes/index.html +++ b/odoc/next/infer/Pulselib/PulseCanonValue/Make/Attributes/index.html @@ -62,7 +62,16 @@ t -> (Pulselib.PulseBasicInterface.Timestamp.t * Pulselib.PulseBasicInterface.Trace.t) - option
    val add_dynamic_type : + option
    val add_dict_contain_const_keys : t -> t -> t
    val remove_dict_contain_const_keys : t -> t -> t
    val is_dict_contain_const_keys : t -> t -> bool
    val add_dict_read_const_key : + Pulselib.PulseBasicInterface.Timestamp.t -> + Pulselib.PulseBasicInterface.Trace.t -> + t -> + IR.Fieldname.t -> + t -> + t
    val get_dict_read_const_keys : + t -> + t -> + Pulselib.PulseBasicInterface.Attribute.ConstKeys.t option
    val add_dynamic_type : Pulselib.PulseBasicInterface.Attribute.dynamic_type_data -> t -> t -> diff --git a/odoc/next/infer/Pulselib/PulseCanonValue/Make/Memory/Access/index.html b/odoc/next/infer/Pulselib/PulseCanonValue/Make/Memory/Access/index.html index 6b9bdd854fa..0fb25238681 100644 --- a/odoc/next/infer/Pulselib/PulseCanonValue/Make/Memory/Access/index.html +++ b/odoc/next/infer/Pulselib/PulseCanonValue/Make/Memory/Access/index.html @@ -1,6 +1,6 @@ Access (infer.Pulselib.PulseCanonValue.Make.Memory.Access)

    Module Memory.Access

    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType - with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Attributes/index.html b/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Attributes/index.html index c8a1a0c17c6..22443a508a2 100644 --- a/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Attributes/index.html +++ b/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Attributes/index.html @@ -62,7 +62,16 @@ t -> (Pulselib.PulseBasicInterface.Timestamp.t * Pulselib.PulseBasicInterface.Trace.t) - option
    val add_dynamic_type : + option
    val add_dict_contain_const_keys : t -> t -> t
    val remove_dict_contain_const_keys : t -> t -> t
    val is_dict_contain_const_keys : t -> t -> bool
    val add_dict_read_const_key : + Pulselib.PulseBasicInterface.Timestamp.t -> + Pulselib.PulseBasicInterface.Trace.t -> + t -> + IR.Fieldname.t -> + t -> + t
    val get_dict_read_const_keys : + t -> + t -> + Pulselib.PulseBasicInterface.Attribute.ConstKeys.t option
    val add_dynamic_type : Pulselib.PulseBasicInterface.Attribute.dynamic_type_data -> t -> t -> diff --git a/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Memory/Access/index.html b/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Memory/Access/index.html index 85f17f9be99..64df80e6987 100644 --- a/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Memory/Access/index.html +++ b/odoc/next/infer/Pulselib/PulseCanonValue/module-type-S/Memory/Access/index.html @@ -1,6 +1,6 @@ Access (infer.Pulselib.PulseCanonValue.S.Memory.Access)

    Module Memory.Access

    include IStdlib.PrettyPrintable.PrintableEquatableOrderedType - with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val is_strong_access : IR.Tenv.t -> t -> bool
    val canonicalize : + with type t = t Absint.MemoryAccess.t
    include IStdlib.IStd.Caml.Set.OrderedType with type t = t Absint.MemoryAccess.t
    val compare : t -> t -> int
    include IStdlib.PrettyPrintable.PrintableEquatableType with type t := t
    include IStdlib.PrettyPrintable.PrintableType with type t := t
    val pp : IStdlib.PrettyPrintable.F.formatter -> t -> unit
    val equal : t -> t -> bool
    val canonicalize : get_var_repr:(PulseAbstractValue.t -> PulseAbstractValue.t) -> t -> t
    val yojson_of_t : t -> Yojson.Safe.t
    module Set : IStdlib.IStd.Caml.Set.S with type elt = t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseDecompiler/index.html b/odoc/next/infer/Pulselib/PulseDecompiler/index.html index 72a5278c4ee..7c01f17ace4 100644 --- a/odoc/next/infer/Pulselib/PulseDecompiler/index.html +++ b/odoc/next/infer/Pulselib/PulseDecompiler/index.html @@ -1,13 +1,7 @@ -PulseDecompiler (infer.Pulselib.PulseDecompiler)

    Module Pulselib.PulseDecompiler

    module F = Stdlib.Format
    module AbstractValue = PulseAbstractValue
    module Access = PulseAccess
    module BaseAddressAttributes = PulseBaseAddressAttributes
    module CallEvent = PulseCallEvent
    module DecompilerExpr = PulseDecompilerExpr
    module ValueHistory = PulseValueHistory

    Describe abstract values in terms of source code elements

    type key = AbstractValue.t
    type t
    val pp : F.formatter -> t -> unit
    val empty : t
    val invalid : t
    val add_var_source : key -> IR.Var.t -> t -> t
    val add_call_source : +PulseDecompiler (infer.Pulselib.PulseDecompiler)

    Module Pulselib.PulseDecompiler

    module F = Stdlib.Format
    module AbstractValue = PulseAbstractValue
    module Access = PulseAccess
    module CallEvent = PulseCallEvent
    module DecompilerExpr = PulseDecompilerExpr
    module ValueHistory = PulseValueHistory

    Describe abstract values in terms of source code elements

    type key = AbstractValue.t
    type t
    val pp : F.formatter -> t -> unit
    val empty : t
    val invalid : t
    val add_var_source : key -> IR.Var.t -> t -> t
    val add_block_source : key -> string -> t -> t
    val add_call_source : key -> CallEvent.t -> ((AbstractValue.t * ValueHistory.t) * IR.Typ.t) list -> t -> - t
    val add_access_source : - key -> - Access.t -> - src:key -> - BaseAddressAttributes.t -> - t -> - t
    \ No newline at end of file + t
    val add_access_source : key -> Access.t -> src:key -> t -> t
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseDecompilerExpr/index.html b/odoc/next/infer/Pulselib/PulseDecompilerExpr/index.html index 8d01e81bb68..486322514ee 100644 --- a/odoc/next/infer/Pulselib/PulseDecompilerExpr/index.html +++ b/odoc/next/infer/Pulselib/PulseDecompilerExpr/index.html @@ -1,2 +1,2 @@ -PulseDecompilerExpr (infer.Pulselib.PulseDecompilerExpr)

    Module Pulselib.PulseDecompilerExpr

    module F = Stdlib.Format
    module AbstractValue = PulseAbstractValue
    module CallEvent = PulseCallEvent
    type base =
    1. | PVar of IR.Pvar.t
    2. | ReturnValue of CallEvent.t
    val compare_base : base -> base -> int
    val equal_base : base -> base -> bool
    type access =
    1. | CaptureFieldAccess of IR.CapturedVar.t
    2. | FieldAccess of IR.Fieldname.t
    3. | ArrayAccess of source_expr option
    4. | TakeAddress
    5. | Dereference
    and source_expr = base * access list
    val compare_access : access -> access -> int
    val compare_source_expr : source_expr -> source_expr -> int
    val equal_access : access -> access -> bool
    val equal_source_expr : source_expr -> source_expr -> bool
    type t =
    1. | SourceExpr of source_expr * AbstractValue.t option
    2. | Unknown of AbstractValue.t option
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    val pp_source_expr : F.formatter -> source_expr -> unit
    val pp_with_abstract_value : Stdlib.Format.formatter -> t -> unit
    val abstract_value_of_expr : t -> AbstractValue.t option
    val is_unknown : t -> bool
    val yojson_of_t : t -> Yojson.Safe.t
    val reset_abstract_value : t -> t

    forget the underlying abstract value in the argument: abstract_value_of_expr (reset_abstract_value expr) is None

    \ No newline at end of file +PulseDecompilerExpr (infer.Pulselib.PulseDecompilerExpr)

    Module Pulselib.PulseDecompilerExpr

    module F = Stdlib.Format
    module AbstractValue = PulseAbstractValue
    module CallEvent = PulseCallEvent
    type base =
    1. | PVar of IR.Pvar.t
    2. | Block of string
    3. | ReturnValue of CallEvent.t
    val compare_base : base -> base -> int
    val equal_base : base -> base -> bool
    type access =
    1. | CaptureFieldAccess of string
    2. | FieldAccess of IR.Fieldname.t
    3. | ArrayAccess of source_expr option
    4. | TakeAddress
    5. | Dereference
    and source_expr = base * access list
    val compare_access : access -> access -> int
    val compare_source_expr : source_expr -> source_expr -> int
    val equal_access : access -> access -> bool
    val equal_source_expr : source_expr -> source_expr -> bool
    type t =
    1. | SourceExpr of source_expr * AbstractValue.t option
    2. | Unknown of AbstractValue.t option
    include Ppx_compare_lib.Comparable.S with type t := t
    val compare : t Base__Ppx_compare_lib.compare
    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    val pp_source_expr : F.formatter -> source_expr -> unit
    val pp_with_abstract_value : Stdlib.Format.formatter -> t -> unit
    val abstract_value_of_expr : t -> AbstractValue.t option
    val is_unknown : t -> bool
    val yojson_of_t : t -> Yojson.Safe.t
    val reset_abstract_value : t -> t

    forget the underlying abstract value in the argument: abstract_value_of_expr (reset_abstract_value expr) is None

    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseDiagnostic/index.html b/odoc/next/infer/Pulselib/PulseDiagnostic/index.html index 07da44f5d2a..8d55152080d 100644 --- a/odoc/next/infer/Pulselib/PulseDiagnostic/index.html +++ b/odoc/next/infer/Pulselib/PulseDiagnostic/index.html @@ -7,4 +7,4 @@ access_to_invalid_address -> bool
    val yojson_of_access_to_invalid_address : access_to_invalid_address -> - Ppx_yojson_conv_lib.Yojson.Safe.t
    module ErlangError : sig ... end
    module ReadUninitialized : sig ... end
    type flow_kind =
    1. | TaintedFlow
    2. | FlowToSink
    3. | FlowFromSource
    val equal_flow_kind : flow_kind -> flow_kind -> bool
    type t =
    1. | AccessToInvalidAddress of access_to_invalid_address
    2. | ConfigUsage of {
      1. pname : IR.Procname.t;
      2. config : ConfigName.t;
      3. branch_location : IBase.Location.t;
      4. location : IBase.Location.t;
      5. trace : Trace.t;
      }
    3. | ConstRefableParameter of {
      1. param : IR.Var.t;
      2. typ : IR.Typ.t;
      3. location : IBase.Location.t;
      }
    4. | CSharpResourceLeak of {
      1. class_name : IR.CSharpClassName.t;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    5. | ErlangError of ErlangError.t
    6. | TransitiveAccess of {
      1. tag : string;
      2. description : string;
      3. call_trace : Trace.t;
      4. transitive_callees : TransitiveInfo.Callees.t;
      5. transitive_missed_captures : IR.Typ.Name.Set.t;
      }
    7. | JavaResourceLeak of {
      1. class_name : IR.JavaClassName.t;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    8. | HackUnawaitedAwaitable of {
      1. allocation_trace : Trace.t;
      2. location : IBase.Location.t;
      }
    9. | MemoryLeak of {
      1. allocator : Attribute.allocator;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    10. | ReadonlySharedPtrParameter of {
      1. param : IR.Var.t;
      2. typ : IR.Typ.t;
      3. location : IBase.Location.t;
      4. used_locations : IBase.Location.t list;
      }
    11. | ReadUninitialized of ReadUninitialized.t
    12. | RetainCycle of {
      1. assignment_traces : Trace.t list;
      2. value : DecompilerExpr.t;
      3. path : DecompilerExpr.t;
      4. location : IBase.Location.t;
      }
    13. | StackVariableAddressEscape of {
      1. variable : IR.Var.t;
      2. history : ValueHistory.t;
      3. location : IBase.Location.t;
      }
    14. | TaintFlow of {
      1. expr : DecompilerExpr.t;
      2. source : TaintItem.t * ValueHistory.t;
      3. sink : TaintItem.t * Trace.t;
      4. location : IBase.Location.t;
      5. flow_kind : flow_kind;
      6. policy_description : string;
      7. policy_id : int;
      8. policy_privacy_effect : string option;
      }
    15. | UnnecessaryCopy of {
      1. copied_into : PulseAttribute.CopiedInto.t;
      2. source_typ : IR.Typ.t option;
      3. source_opt : DecompilerExpr.source_expr option;
      4. location : IBase.Location.t;
      5. copied_location : (IR.Procname.t * IBase.Location.t) option;
      6. location_instantiated : IBase.Location.t option;
      7. from : PulseAttribute.CopyOrigin.t;
      }

    an error to report to the user

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    val aborts_execution : t -> bool

    whether the presence of an error should abort the execution

    val get_message_and_suggestion : t -> string * string option
    val get_location : t -> IBase.Location.t
    val get_location_instantiated : t -> IBase.Location.t option
    val get_copy_type : t -> IR.Typ.t option
    val get_issue_type : latent:bool -> t -> IBase.IssueType.t
    val get_trace : t -> Absint.Errlog.loc_trace
    \ No newline at end of file + Ppx_yojson_conv_lib.Yojson.Safe.t
    module ErlangError : sig ... end
    module ReadUninitialized : sig ... end
    type flow_kind =
    1. | TaintedFlow
    2. | FlowToSink
    3. | FlowFromSource
    val equal_flow_kind : flow_kind -> flow_kind -> bool
    type t =
    1. | AccessToInvalidAddress of access_to_invalid_address
    2. | ConfigUsage of {
      1. pname : IR.Procname.t;
      2. config : ConfigName.t;
      3. branch_location : IBase.Location.t;
      4. location : IBase.Location.t;
      5. trace : Trace.t;
      }
    3. | ConstRefableParameter of {
      1. param : IR.Var.t;
      2. typ : IR.Typ.t;
      3. location : IBase.Location.t;
      }
    4. | CSharpResourceLeak of {
      1. class_name : IR.CSharpClassName.t;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    5. | ErlangError of ErlangError.t
    6. | TransitiveAccess of {
      1. tag : string;
      2. description : string;
      3. call_trace : Trace.t;
      4. transitive_callees : TransitiveInfo.Callees.t;
      5. transitive_missed_captures : IR.Typ.Name.Set.t;
      }
    7. | JavaResourceLeak of {
      1. class_name : IR.JavaClassName.t;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    8. | HackUnawaitedAwaitable of {
      1. allocation_trace : Trace.t;
      2. location : IBase.Location.t;
      }
    9. | MemoryLeak of {
      1. allocator : Attribute.allocator;
      2. allocation_trace : Trace.t;
      3. location : IBase.Location.t;
      }
    10. | ReadonlySharedPtrParameter of {
      1. param : IR.Var.t;
      2. typ : IR.Typ.t;
      3. location : IBase.Location.t;
      4. used_locations : IBase.Location.t list;
      }
    11. | ReadUninitialized of ReadUninitialized.t
    12. | RetainCycle of {
      1. assignment_traces : Trace.t list;
      2. values : DecompilerExpr.t list;
      3. location : IBase.Location.t;
      }
    13. | StackVariableAddressEscape of {
      1. variable : IR.Var.t;
      2. history : ValueHistory.t;
      3. location : IBase.Location.t;
      }
    14. | TaintFlow of {
      1. expr : DecompilerExpr.t;
      2. source : TaintItem.t * ValueHistory.t;
      3. sink : TaintItem.t * Trace.t;
      4. location : IBase.Location.t;
      5. flow_kind : flow_kind;
      6. policy_description : string;
      7. policy_id : int;
      8. policy_privacy_effect : string option;
      }
    15. | UnnecessaryCopy of {
      1. copied_into : PulseAttribute.CopiedInto.t;
      2. source_typ : IR.Typ.t option;
      3. source_opt : DecompilerExpr.source_expr option;
      4. location : IBase.Location.t;
      5. copied_location : (IR.Procname.t * IBase.Location.t) option;
      6. location_instantiated : IBase.Location.t option;
      7. from : PulseAttribute.CopyOrigin.t;
      }

    an error to report to the user

    include Ppx_compare_lib.Equal.S with type t := t
    val equal : t Base__Ppx_compare_lib.equal
    val pp : F.formatter -> t -> unit
    val aborts_execution : t -> bool

    whether the presence of an error should abort the execution

    val get_message_and_suggestion : t -> string * string option
    val get_location : t -> IBase.Location.t
    val get_location_instantiated : t -> IBase.Location.t option
    val get_copy_type : t -> IR.Typ.t option
    val get_issue_type : latent:bool -> t -> IBase.IssueType.t
    val get_trace : t -> Absint.Errlog.loc_trace
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseInterproc/index.html b/odoc/next/infer/Pulselib/PulseInterproc/index.html index 8781752de94..3d905a684ad 100644 --- a/odoc/next/infer/Pulselib/PulseInterproc/index.html +++ b/odoc/next/infer/Pulselib/PulseInterproc/index.html @@ -1,12 +1,12 @@ -PulseInterproc (infer.Pulselib.PulseInterproc)

    Module Pulselib.PulseInterproc

    type call_state
    type contradiction = private
    1. | Aliasing of {
      1. addr_caller : Pulselib.PulseBasicInterface.AbstractValue.t;
      2. addr_callee : Pulselib.PulseBasicInterface.AbstractValue.t;
      3. addr_callee' : Pulselib.PulseBasicInterface.AbstractValue.t;
      4. call_state : call_state;
      }
      (*

      raised when the precondition and the current state disagree on the aliasing, i.e. some addresses callee_addr and callee_addr' that are distinct in the pre are aliased to a single address caller_addr in the caller's current state. Typically raised when calling foo(z,z) where the spec for foo(x,y) says that x and y are disjoint.

      *)
    2. | DynamicTypeNeeded of Pulselib.PulseBasicInterface.AbstractValue.t - IR.Specialization.HeapPath.Map.t
      (*

      A map path -> value such that each path leads to a value (in the caller space) that requires dynamic type specialization

      *)
    3. | CapturedFormalActualLength of {
      1. captured_formals : (IR.Var.t * IR.Typ.t) list;
      2. captured_actuals : ((Pulselib.PulseBasicInterface.AbstractValue.t +PulseInterproc (infer.Pulselib.PulseInterproc)

        Module Pulselib.PulseInterproc

        type call_state
        type contradiction = private
        1. | Aliasing of {
          1. addr_caller : Pulselib.PulseBasicInterface.AbstractValue.t;
          2. addr_callee : Pulselib.PulseBasicInterface.AbstractValue.t;
          3. addr_callee' : Pulselib.PulseBasicInterface.AbstractValue.t;
          4. call_state : call_state;
          }
          (*

          raised when the precondition and the current state disagree on the aliasing, i.e. some addresses callee_addr and callee_addr' that are distinct in the pre are aliased to a single address caller_addr in the caller's current state. Typically raised when calling foo(z,z) where the spec for foo(x,y) says that x and y are disjoint. We only raise this information if we have found this alias through a heap path that is not supported by our current abstraction (like array accesses).

          *)
        2. | AliasingWithAllAliases of IR.Specialization.HeapPath.t list list
          (*

          similar to Aliasing case above but we have collected in a list of alias classes all alias information before raising and all of them rely on heap paths that we support.

          *)
        3. | DynamicTypeNeeded of Pulselib.PulseBasicInterface.AbstractValue.t + IR.Specialization.HeapPath.Map.t
          (*

          A map path -> value such that each path leads to a value (in the caller space) that requires dynamic type specialization

          *)
        4. | CapturedFormalActualLength of {
          1. captured_formals : (IR.Pvar.t * IR.Typ.t) list;
          2. captured_actuals : ((Pulselib.PulseBasicInterface.AbstractValue.t * Pulselib.PulseBasicInterface.ValueHistory.t) * IR.Typ.t) - list;
          }
        5. | FormalActualLength of {
          1. formals : (IR.Var.t * IR.Typ.t) list;
          2. actuals : ((Pulselib.PulseBasicInterface.AbstractValue.t + list;
          }
        6. | FormalActualLength of {
          1. formals : (IR.Pvar.t * IR.Typ.t) list;
          2. actuals : ((Pulselib.PulseBasicInterface.AbstractValue.t * Pulselib.PulseBasicInterface.ValueHistory.t) * IR.Typ.t) - list;
          }
        7. | PathCondition
        val is_aliasing_contradiction : contradiction -> bool
        val is_dynamic_type_needed_contradiction : + list;
      }
    4. | PathCondition
    val merge_contradictions : @@ -17,13 +17,13 @@ IR.Procname.t -> IBase.Location.t -> callee_summary:Pulselib.PulseDomainInterface.AbductiveDomain.Summary.t -> - captured_formals:(IR.Var.t * IR.Typ.t) list -> + captured_formals:(IR.Pvar.t * IR.Typ.t) list -> captured_actuals: ((Pulselib.PulseBasicInterface.AbstractValue.t * Pulselib.PulseBasicInterface.ValueHistory.t) * IR.Typ.t) list -> - formals:(IR.Var.t * IR.Typ.t) list -> + formals:(IR.Pvar.t * IR.Typ.t) list -> actuals: ((Pulselib.PulseBasicInterface.AbstractValue.t * Pulselib.PulseBasicInterface.ValueHistory.t) diff --git a/odoc/next/infer/Pulselib/PulseModelsCpp/Function/index.html b/odoc/next/infer/Pulselib/PulseModelsCpp/Function/index.html index cff60a30275..a947fdfe113 100644 --- a/odoc/next/infer/Pulselib/PulseModelsCpp/Function/index.html +++ b/odoc/next/infer/Pulselib/PulseModelsCpp/Function/index.html @@ -2,9 +2,9 @@ Function (infer.Pulselib.PulseModelsCpp.Function)

    Module PulseModelsCpp.Function

    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseModelsDSL/Syntax/index.html b/odoc/next/infer/Pulselib/PulseModelsDSL/Syntax/index.html index f5c84974e2f..434cf595540 100644 --- a/odoc/next/infer/Pulselib/PulseModelsDSL/Syntax/index.html +++ b/odoc/next/infer/Pulselib/PulseModelsDSL/Syntax/index.html @@ -1,5 +1,5 @@ -Syntax (infer.Pulselib.PulseModelsDSL.Syntax)

    Module PulseModelsDSL.Syntax

    val let* : 'a model_monad -> ('a -> 'b model_monad) -> 'b model_monad
    val ret : 'a -> 'a model_monad
    val unreachable : 'a model_monad
    val list_fold : +Syntax (infer.Pulselib.PulseModelsDSL.Syntax)

    Module PulseModelsDSL.Syntax

    val let* : 'a model_monad -> ('a -> 'b model_monad) -> 'b model_monad
    val ret : 'a -> 'a model_monad
    val throw : unit model_monad
    val unreachable : 'a model_monad
    val list_fold : 'a list -> init:'accum -> f:('accum -> 'a -> 'accum model_monad) -> @@ -30,7 +30,7 @@ unit model_monad
    val disjuncts : 'a model_monad list -> 'a model_monad
    val start_model : unit model_monad -> PulseModelsImport.model

    get a model from a disjunctive model_monad

    val lift_to_monad : PulseModelsImport.model -> unit model_monad

    beware that the model may modify the PulseModelsImport.model_data.ret field

    val lift_to_monad_and_get_result : PulseModelsImport.model -> aval model_monad

    apply the model and return its result. fails if the model did not assign the reserved model_data.ret variable.

    val add_dynamic_type : IR.Typ.t -> aval -> unit model_monad
    val add_static_type : IR.Typ.name -> aval -> unit model_monad
    val deep_copy : ?depth_max:int -> aval -> aval model_monad
    val eval_binop : IR.Binop.t -> aval -> aval -> aval model_monad
    val eval_binop_int : IR.Binop.t -> aval -> IR.IntLit.t -> aval model_monad
    val eval_read : IR.Exp.t -> aval model_monad
    val eval_to_value_origin : + unit model_monad
    val add_dict_contain_const_keys : aval -> unit model_monad
    val add_dict_read_const_key : aval -> IR.Fieldname.t -> unit model_monad
    val remove_dict_contain_const_keys : aval -> unit model_monad
    val add_dynamic_type : IR.Typ.t -> aval -> unit model_monad
    val add_static_type : IR.Typ.name -> aval -> unit model_monad
    val deep_copy : ?depth_max:int -> aval -> aval model_monad
    val eval_binop : IR.Binop.t -> aval -> aval -> aval model_monad
    val eval_binop_int : IR.Binop.t -> aval -> IR.IntLit.t -> aval model_monad
    val eval_read : IR.Exp.t -> aval model_monad
    val eval_const_int : int -> aval model_monad
    val eval_const_string : string -> aval model_monad
    val eval_access : ?desc:string -> diff --git a/odoc/next/infer/Pulselib/PulseModelsImport/Basic/index.html b/odoc/next/infer/Pulselib/PulseModelsImport/Basic/index.html index 45855d05620..30bf151378f 100644 --- a/odoc/next/infer/Pulselib/PulseModelsImport/Basic/index.html +++ b/odoc/next/infer/Pulselib/PulseModelsImport/Basic/index.html @@ -83,7 +83,7 @@ IR.Typ.name -> IR.Typ.t list -> Pulselib.PulseBasicInterface.ValueOrigin.t - Pulselib.PulseAliasSpecialization.FuncArg.t + Absint.ProcnameDispatcher.Call.FuncArg.t list -> IR.Exp.t -> model_data -> diff --git a/odoc/next/infer/Pulselib/PulseModelsImport/index.html b/odoc/next/infer/Pulselib/PulseModelsImport/index.html index 3b577a0f561..969bb9ffb89 100644 --- a/odoc/next/infer/Pulselib/PulseModelsImport/index.html +++ b/odoc/next/infer/Pulselib/PulseModelsImport/index.html @@ -4,7 +4,7 @@ (IR.Ident.t * IR.Typ.t) -> IR.Exp.t -> (IR.Exp.t * IR.Typ.t) list -> - arg_payload Pulselib.PulseAliasSpecialization.FuncArg.t list -> + arg_payload Absint.ProcnameDispatcher.Call.FuncArg.t list -> IBase.Location.t -> IR.CallFlags.t -> Pulselib.PulseDomainInterface.AbductiveDomain.t -> diff --git a/odoc/next/infer/Pulselib/PulseOperations/index.html b/odoc/next/infer/Pulselib/PulseOperations/index.html index 260c25b4164..24726ed8daa 100644 --- a/odoc/next/infer/Pulselib/PulseOperations/index.html +++ b/odoc/next/infer/Pulselib/PulseOperations/index.html @@ -115,6 +115,11 @@ IR.Exp.t -> Pulselib.PulseBasicInterface.AbstractValue.t -> t -> + t
    val add_static_type_objc_class : + IR.Tenv.t -> + IR.Typ.t -> + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> t
    val havoc_id : IR.Ident.t -> Pulselib.PulseBasicInterface.ValueHistory.t -> @@ -218,12 +223,24 @@ recursive:bool -> Pulselib.PulseBasicInterface.AbstractValue.t -> t -> - t

    releases the resource of the argument, and recursively calls itself on the delegated resource if recursive==true

    val add_dynamic_type : + t

    releases the resource of the argument, and recursively calls itself on the delegated resource if recursive==true

    val add_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val remove_dict_contain_const_keys : + Pulselib.PulseBasicInterface.AbstractValue.t -> + t -> + t
    val add_dynamic_type : IR.Typ.t -> ?source_file:IBase.SourceFile.t -> Pulselib.PulseBasicInterface.AbstractValue.t -> t -> - t
    val is_ref_counted : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> bool
    val remove_allocation_attr : + t
    val remove_allocation_attr : Pulselib.PulseBasicInterface.AbstractValue.t -> t -> t
    val invalidate_access : @@ -286,7 +303,7 @@ IR.Procname.t -> Pulselib.PulseDomainInterface.PathContext.t -> IBase.Location.t -> - captured_formals:(IR.Var.t * IR.CapturedVar.capture_mode * IR.Typ.t) list -> + captured_formals:(IR.Pvar.t * IR.CapturedVar.capture_mode * IR.Typ.t) list -> call_kind:call_kind -> actuals: ((Pulselib.PulseBasicInterface.AbstractValue.t diff --git a/odoc/next/infer/Pulselib/PulseRefCounting/index.html b/odoc/next/infer/Pulselib/PulseRefCounting/index.html index f17d6e915d8..2ecbaf26ad7 100644 --- a/odoc/next/infer/Pulselib/PulseRefCounting/index.html +++ b/odoc/next/infer/Pulselib/PulseRefCounting/index.html @@ -6,4 +6,4 @@ IR.Tenv.t -> Pulselib.PulseDomainInterface.AbductiveDomain.t -> IR.Var.t list -> - IR.Var.t list
    \ No newline at end of file + IR.Var.t list
    val is_strong_access : IR.Tenv.t -> 'a Absint.MemoryAccess.t -> bool
    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseRetainCycleChecker/index.html b/odoc/next/infer/Pulselib/PulseRetainCycleChecker/index.html new file mode 100644 index 00000000000..b6102597021 --- /dev/null +++ b/odoc/next/infer/Pulselib/PulseRetainCycleChecker/index.html @@ -0,0 +1,18 @@ + +PulseRetainCycleChecker (infer.Pulselib.PulseRetainCycleChecker)

    Module Pulselib.PulseRetainCycleChecker

    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/PulseSpecialization/index.html b/odoc/next/infer/Pulselib/PulseSpecialization/index.html new file mode 100644 index 00000000000..d7e6f7426e4 --- /dev/null +++ b/odoc/next/infer/Pulselib/PulseSpecialization/index.html @@ -0,0 +1,5 @@ + +PulseSpecialization (infer.Pulselib.PulseSpecialization)

    Module Pulselib.PulseSpecialization

    \ No newline at end of file diff --git a/odoc/next/infer/Pulselib/index.html b/odoc/next/infer/Pulselib/index.html index a8806c0235c..75c4466ba53 100644 --- a/odoc/next/infer/Pulselib/index.html +++ b/odoc/next/infer/Pulselib/index.html @@ -1,2 +1,2 @@ -Pulselib (infer.Pulselib)

    Module Pulselib

    module Pulse : sig ... end
    module PulseAbductiveDecompiler : sig ... end
    module PulseAbductiveDomain : sig ... end
    module PulseAbstractValue : sig ... end
    module PulseAccess : sig ... end
    module PulseAccessResult : sig ... end
    module PulseAliasSpecialization : sig ... end
    module PulseArithmetic : sig ... end
    module PulseAttribute : sig ... end
    module PulseBaseAddressAttributes : sig ... end
    module PulseBaseDomain : sig ... end
    module PulseBaseMemory : sig ... end
    module PulseBaseStack : sig ... end
    module PulseBasicInterface : sig ... end

    Basic Pulse modules that are safe to use in any module

    module PulseCItv : sig ... end
    module PulseCallEvent : sig ... end
    module PulseCallOperations : sig ... end
    module PulseCanonValue : sig ... end
    module PulseCheapCopyTypes : sig ... end
    module PulseCurrentProcedure : sig ... end
    module PulseDecompiler : sig ... end
    module PulseDecompilerExpr : sig ... end
    module PulseDiagnostic : sig ... end
    module PulseDomainInterface : sig ... end
    module PulseExecutionDomain : sig ... end
    module PulseFormula : sig ... end
    module PulseInterproc : sig ... end
    module PulseInvalidation : sig ... end
    module PulseLatentIssue : sig ... end
    module PulseLoadInstrModels : sig ... end
    module PulseModels : sig ... end
    module PulseModelsAndroid : sig ... end
    module PulseModelsC : sig ... end
    module PulseModelsCSharp : sig ... end
    module PulseModelsCpp : sig ... end
    module PulseModelsDSL : sig ... end
    module PulseModelsErlang : sig ... end
    module PulseModelsHack : sig ... end
    module PulseModelsImport : sig ... end
    module PulseModelsJava : sig ... end
    module PulseModelsLocks : sig ... end
    module PulseModelsObjC : sig ... end
    module PulseModelsOptional : sig ... end
    module PulseModelsSmartPointers : sig ... end
    module PulseNonDisjunctiveDomain : sig ... end
    module PulseNonDisjunctiveOperations : sig ... end
    module PulseOperationResult : sig ... end
    module PulseOperations : sig ... end
    module PulsePathContext : sig ... end
    module PulseRefCounting : sig ... end
    module PulseReport : sig ... end
    module PulseResult : sig ... end
    module PulseSatUnsat : sig ... end
    module PulseSkippedCalls : sig ... end
    module PulseSummary : sig ... end
    module PulseTaintConfig : sig ... end
    module PulseTaintItem : sig ... end
    module PulseTaintItemMatcher : sig ... end
    module PulseTaintOperations : sig ... end
    module PulseTimestamp : sig ... end
    module PulseTopl : sig ... end
    module PulseTrace : sig ... end
    module PulseTransitiveAccessChecker : sig ... end
    module PulseTransitiveInfo : sig ... end
    module PulseUninitBlocklist : sig ... end
    module PulseValueHistory : sig ... end
    module PulseValueOrigin : sig ... end
    module QSafeCapped : sig ... end
    module ZSafe : sig ... end
    \ No newline at end of file +Pulselib (infer.Pulselib)

    Module Pulselib

    module Pulse : sig ... end
    module PulseAbductiveDecompiler : sig ... end
    module PulseAbductiveDomain : sig ... end
    module PulseAbstractValue : sig ... end
    module PulseAccess : sig ... end
    module PulseAccessResult : sig ... end
    module PulseArithmetic : sig ... end
    module PulseAttribute : sig ... end
    module PulseBaseAddressAttributes : sig ... end
    module PulseBaseDomain : sig ... end
    module PulseBaseMemory : sig ... end
    module PulseBaseStack : sig ... end
    module PulseBasicInterface : sig ... end

    Basic Pulse modules that are safe to use in any module

    module PulseCItv : sig ... end
    module PulseCallEvent : sig ... end
    module PulseCallOperations : sig ... end
    module PulseCanonValue : sig ... end
    module PulseCheapCopyTypes : sig ... end
    module PulseCurrentProcedure : sig ... end
    module PulseDecompiler : sig ... end
    module PulseDecompilerExpr : sig ... end
    module PulseDiagnostic : sig ... end
    module PulseDomainInterface : sig ... end
    module PulseExecutionDomain : sig ... end
    module PulseFormula : sig ... end
    module PulseInterproc : sig ... end
    module PulseInvalidation : sig ... end
    module PulseLatentIssue : sig ... end
    module PulseLoadInstrModels : sig ... end
    module PulseModels : sig ... end
    module PulseModelsAndroid : sig ... end
    module PulseModelsC : sig ... end
    module PulseModelsCSharp : sig ... end
    module PulseModelsCpp : sig ... end
    module PulseModelsDSL : sig ... end
    module PulseModelsErlang : sig ... end
    module PulseModelsHack : sig ... end
    module PulseModelsImport : sig ... end
    module PulseModelsJava : sig ... end
    module PulseModelsLocks : sig ... end
    module PulseModelsObjC : sig ... end
    module PulseModelsOptional : sig ... end
    module PulseModelsSmartPointers : sig ... end
    module PulseNonDisjunctiveDomain : sig ... end
    module PulseNonDisjunctiveOperations : sig ... end
    module PulseOperationResult : sig ... end
    module PulseOperations : sig ... end
    module PulsePathContext : sig ... end
    module PulseRefCounting : sig ... end
    module PulseReport : sig ... end
    module PulseResult : sig ... end
    module PulseRetainCycleChecker : sig ... end
    module PulseSatUnsat : sig ... end
    module PulseSkippedCalls : sig ... end
    module PulseSpecialization : sig ... end
    module PulseSummary : sig ... end
    module PulseTaintConfig : sig ... end
    module PulseTaintItem : sig ... end
    module PulseTaintItemMatcher : sig ... end
    module PulseTaintOperations : sig ... end
    module PulseTimestamp : sig ... end
    module PulseTopl : sig ... end
    module PulseTrace : sig ... end
    module PulseTransitiveAccessChecker : sig ... end
    module PulseTransitiveInfo : sig ... end
    module PulseUninitBlocklist : sig ... end
    module PulseValueHistory : sig ... end
    module PulseValueOrigin : sig ... end
    module QSafeCapped : sig ... end
    module ZSafe : sig ... end
    \ No newline at end of file diff --git a/odoc/next/infer/Textuallib/TextualParser/index.html b/odoc/next/infer/Textuallib/TextualParser/index.html index 45e1ca52cfc..9f1e517f37c 100644 --- a/odoc/next/infer/Textuallib/TextualParser/index.html +++ b/odoc/next/infer/Textuallib/TextualParser/index.html @@ -1,5 +1,5 @@ -TextualParser (infer.Textuallib.TextualParser)

    Module Textuallib.TextualParser

    module F = Stdlib.Format
    type error =
    1. | SyntaxError of {
      1. loc : Textual.Location.t;
      2. msg : string;
      }
    2. | BasicError of TextualBasicVerification.error
    3. | TypeError of TextualTypeVerification.error
    4. | TransformError of Textual.transform_error list
    5. | DeclaredTwiceError of TextualDecls.error
      (*

      errors related to Textual

      *)
    val pp_error : Textual.SourceFile.t -> F.formatter -> error -> unit
    val parse_string : +TextualParser (infer.Textuallib.TextualParser)

    Module Textuallib.TextualParser

    module F = Stdlib.Format
    type error =
    1. | SyntaxError of {
      1. loc : Textual.Location.t;
      2. msg : string;
      }
    2. | BasicError of TextualBasicVerification.error
    3. | TypeError of TextualTypeVerification.error
    4. | TransformError of Textual.transform_error list
    5. | DeclaredTwiceError of TextualDecls.error
      (*

      errors related to Textual

      *)
    val pp_error : Textual.SourceFile.t -> F.formatter -> error -> unit
    val error_to_string : Textual.SourceFile.t -> error -> string
    val parse_string : Textual.SourceFile.t -> string -> (Textual.Module.t, error list) IStdlib.IStd.result
    module TextualFile : sig ... end
    val capture : TextualFile.t list -> unit

    turn a list of textual files into a SIL-Java program and capture them.

    \ No newline at end of file diff --git a/odoc/next/infer/Textuallib/TextualSil/index.html b/odoc/next/infer/Textuallib/TextualSil/index.html index 366ae11c8eb..72473c920c5 100644 --- a/odoc/next/infer/Textuallib/TextualSil/index.html +++ b/odoc/next/infer/Textuallib/TextualSil/index.html @@ -2,4 +2,4 @@ TextualSil (infer.Textuallib.TextualSil)

    Module Textuallib.TextualSil

    val proc_decl_to_sil : Textual.Lang.t -> Textual.ProcDecl.t -> IR.Procname.t
    val module_to_sil : Textual.Module.t -> IR.Cfg.t * IR.Tenv.t
    val from_java : filename:string -> IR.Tenv.t -> IR.Cfg.t -> unit

    generate a .sil file with name filename containing all the functions in the given cfg

    val dump_module : filename:string -> Textual.Module.t -> unit

    generate a .sil file with name filename with all the content of the input module

    val default_return_type : Textual.Lang.t option -> Textual.Location.t -> - Textual.Typ.t
    val hack_dict_type_name : IR.Typ.name
    val hack_dict_iter_type_name : IR.Typ.name
    val hack_vec_type_name : IR.Typ.name
    val hack_vec_iter_type_name : IR.Typ.name
    val hack_bool_type_name : IR.Typ.name
    val hack_int_type_name : IR.Typ.name
    val hack_string_type_name : IR.Typ.name
    val hack_mixed_type_name : IR.Typ.name
    val hack_awaitable_type_name : IR.Typ.name
    val hack_mixed_static_companion_type_name : IR.Typ.name
    val hack_builtins_type_name : IR.Typ.name
    val hack_root_type_name : IR.Typ.name
    val wildcard_sil_fieldname : Textual.Lang.t -> string -> IR.Fieldname.t
    val textual_ext : string
    val to_filename : string -> string
    \ No newline at end of file + Textual.Typ.t
    val hack_dict_type_name : IR.Typ.name
    val hack_dict_iter_type_name : IR.Typ.name
    val hack_vec_type_name : IR.Typ.name
    val hack_vec_iter_type_name : IR.Typ.name
    val hack_bool_type_name : IR.Typ.name
    val hack_int_type_name : IR.Typ.name
    val hack_float_type_name : IR.Typ.name
    val hack_string_type_name : IR.Typ.name
    val hack_splated_vec_type_name : IR.Typ.name
    val hack_mixed_type_name : IR.Typ.name
    val hack_awaitable_type_name : IR.Typ.name
    val hack_mixed_static_companion_type_name : IR.Typ.name
    val hack_builtins_type_name : IR.Typ.name
    val hack_root_type_name : IR.Typ.name
    val wildcard_sil_fieldname : Textual.Lang.t -> string -> IR.Fieldname.t
    val textual_ext : string
    val to_filename : string -> string
    \ No newline at end of file diff --git a/search/index.html b/search/index.html index 337e403c072..0ff68177dd5 100644 --- a/search/index.html +++ b/search/index.html @@ -13,7 +13,7 @@ - +