From 99f1e33b86ca98d80a71e681ffeef9da271d78ed Mon Sep 17 00:00:00 2001 From: facebook-github-bot Date: Wed, 13 Mar 2024 09:41:43 +0000 Subject: [PATCH] Deploy website - based on 6471f1adc9fcf7e47fe6de331df73bb7e44c1034 --- 404.html | 4 +- assets/js/07d14bbd.cb4af53a.js | 1 - assets/js/1c7a9c9f.a953a687.js | 1 - assets/js/1c7a9c9f.f02223a9.js | 1 + assets/js/7b1f0035.03e05687.js | 1 + assets/js/7b1f0035.f46eb7ff.js | 1 - assets/js/935f2afb.37b6f415.js | 1 + assets/js/935f2afb.f9b2dd0c.js | 1 - assets/js/c359af60.a486341c.js | 1 + assets/js/c359af60.c62dc728.js | 1 - assets/js/ca86781b.656dd032.js | 1 + assets/js/ca86781b.abeae509.js | 1 - assets/js/e9325e77.166166de.js | 1 - assets/js/e9325e77.b0fe78fe.js | 1 + assets/js/main.53cbafeb.js | 2 - assets/js/main.c71ddf7a.js | 2 + ...CENSE.txt => main.c71ddf7a.js.LICENSE.txt} | 0 assets/js/runtime~main.040defb2.js | 1 - assets/js/runtime~main.55292082.js | 1 + .../index.html | 4 +- .../17/collaboration-with-spotify/index.html | 4 +- .../07/mobileatscale-london-talk/index.html | 4 +- .../06/23/first-opensourceversary/index.html | 4 +- blog/2016/08/30/curryon-rome-talk/index.html | 4 +- blog/2016/11/28/atscale16/index.html | 4 +- .../10/20/ocamlformat-released/index.html | 4 +- blog/archive/index.html | 4 +- blog/index.html | 4 +- docs/1.0.0/about-Infer/index.html | 4 +- docs/1.0.0/absint-framework/index.html | 4 +- docs/1.0.0/advanced-features/index.html | 4 +- docs/1.0.0/all-issue-types/index.html | 4 +- .../analyzing-apps-or-projects/index.html | 4 +- .../index.html | 4 +- docs/1.0.0/checker-biabduction/index.html | 4 +- docs/1.0.0/checker-bufferoverrun/index.html | 4 +- .../index.html | 4 +- docs/1.0.0/checker-cost/index.html | 4 +- docs/1.0.0/checker-eradicate/index.html | 4 +- .../checker-fragment-retains-view/index.html | 4 +- docs/1.0.0/checker-immutable-cast/index.html | 4 +- docs/1.0.0/checker-impurity/index.html | 4 +- .../index.html | 4 +- docs/1.0.0/checker-linters/index.html | 4 +- .../checker-litho-required-props/index.html | 4 +- docs/1.0.0/checker-liveness/index.html | 4 +- docs/1.0.0/checker-loop-hoisting/index.html | 4 +- docs/1.0.0/checker-printf-args/index.html | 4 +- docs/1.0.0/checker-pulse/index.html | 4 +- docs/1.0.0/checker-purity/index.html | 4 +- docs/1.0.0/checker-quandary/index.html | 4 +- docs/1.0.0/checker-racerd/index.html | 4 +- .../checker-resource-leak-lab/index.html | 4 +- docs/1.0.0/checker-self-in-block/index.html | 4 +- docs/1.0.0/checker-siof/index.html | 4 +- docs/1.0.0/checker-starvation/index.html | 4 +- docs/1.0.0/checker-topl-biabd/index.html | 4 +- docs/1.0.0/checker-topl-pulse/index.html | 4 +- docs/1.0.0/checker-uninit/index.html | 4 +- docs/1.0.0/getting-started/index.html | 4 +- docs/1.0.0/hello-world/index.html | 4 +- docs/1.0.0/infer-workflow/index.html | 4 +- docs/1.0.0/internal-API/index.html | 4 +- docs/1.0.0/man-infer-analyze/index.html | 4 +- docs/1.0.0/man-infer-capture/index.html | 4 +- docs/1.0.0/man-infer-compile/index.html | 4 +- docs/1.0.0/man-infer-debug/index.html | 4 +- docs/1.0.0/man-infer-explore/index.html | 4 +- docs/1.0.0/man-infer-help/index.html | 4 +- docs/1.0.0/man-infer-report/index.html | 4 +- docs/1.0.0/man-infer-reportdiff/index.html | 4 +- docs/1.0.0/man-infer-run/index.html | 4 +- docs/1.0.0/man-infer/index.html | 4 +- docs/1.0.0/man-pages/index.html | 4 +- .../index.html | 4 +- docs/1.0.0/steps-for-ci/index.html | 4 +- docs/1.0.0/support/index.html | 4 +- docs/1.0.0/versions/index.html | 4 +- docs/about-Infer/index.html | 4 +- docs/absint-framework/index.html | 4 +- docs/all-issue-types/index.html | 4 +- docs/analyzing-apps-or-projects/index.html | 4 +- .../index.html | 4 +- docs/checker-biabduction/index.html | 4 +- docs/checker-bufferoverrun/index.html | 4 +- .../index.html | 4 +- .../checker-config-impact-analysis/index.html | 4 +- docs/checker-cost/index.html | 4 +- docs/checker-dotnet-resource-leak/index.html | 4 +- docs/checker-eradicate/index.html | 4 +- docs/checker-fragment-retains-view/index.html | 4 +- docs/checker-immutable-cast/index.html | 4 +- docs/checker-impurity/index.html | 4 +- .../index.html | 4 +- docs/checker-linters/index.html | 4 +- docs/checker-litho-required-props/index.html | 4 +- docs/checker-liveness/index.html | 4 +- docs/checker-loop-hoisting/index.html | 4 +- docs/checker-printf-args/index.html | 4 +- docs/checker-pulse/index.html | 4 +- docs/checker-purity/index.html | 4 +- docs/checker-quandary/index.html | 4 +- docs/checker-racerd/index.html | 4 +- docs/checker-resource-leak-lab/index.html | 4 +- docs/checker-self-in-block/index.html | 4 +- docs/checker-siof/index.html | 4 +- docs/checker-starvation/index.html | 4 +- docs/checker-topl/index.html | 4 +- docs/checker-uninit/index.html | 4 +- docs/getting-started/index.html | 4 +- docs/hello-world/index.html | 4 +- docs/infer-workflow/index.html | 4 +- docs/internal-API/index.html | 4 +- docs/man-infer-analyze/index.html | 4 +- docs/man-infer-capture/index.html | 4 +- docs/man-infer-compile/index.html | 4 +- docs/man-infer-debug/index.html | 4 +- docs/man-infer-explore/index.html | 4 +- docs/man-infer-help/index.html | 4 +- docs/man-infer-report/index.html | 4 +- docs/man-infer-reportdiff/index.html | 4 +- docs/man-infer-run/index.html | 4 +- docs/man-infer/index.html | 4 +- docs/man-pages/index.html | 4 +- docs/next/about-Infer/index.html | 6 +-- docs/next/absint-framework/index.html | 4 +- docs/next/all-checkers/index.html | 14 ++---- docs/next/all-issue-types/index.html | 21 ++++---- .../analyzing-apps-or-projects/index.html | 4 +- .../index.html | 8 +-- docs/next/checker-biabduction/index.html | 6 +-- docs/next/checker-bufferoverrun/index.html | 6 +-- .../checker-config-impact-analysis/index.html | 6 +-- docs/next/checker-cost/index.html | 6 +-- docs/next/checker-datalog/index.html | 6 +-- .../checker-fragment-retains-view/index.html | 6 +-- docs/next/checker-impurity/index.html | 6 +-- .../index.html | 6 +-- docs/next/checker-lineage/index.html | 6 +-- .../checker-litho-required-props/index.html | 6 +-- docs/next/checker-liveness/index.html | 6 +-- docs/next/checker-loop-hoisting/index.html | 6 +-- .../index.html | 6 +-- docs/next/checker-printf-args/index.html | 6 +-- docs/next/checker-pulse/index.html | 6 +-- docs/next/checker-purity/index.html | 6 +-- docs/next/checker-quandary/index.html | 6 +-- docs/next/checker-racerd/index.html | 6 +-- .../next/checker-resource-leak-lab/index.html | 6 +-- docs/next/checker-scope-leakage/index.html | 6 +-- docs/next/checker-self-in-block/index.html | 6 +-- docs/next/checker-sil-validation/index.html | 6 +-- docs/next/checker-siof/index.html | 6 +-- docs/next/checker-starvation/index.html | 6 +-- docs/next/checker-topl/index.html | 8 +-- docs/next/checker-uninit/index.html | 38 -------------- docs/next/getting-started/index.html | 4 +- docs/next/hello-world/index.html | 4 +- docs/next/infer-workflow/index.html | 4 +- docs/next/internal-API/index.html | 4 +- docs/next/man-infer-analyze/index.html | 4 +- docs/next/man-infer-capture/index.html | 4 +- docs/next/man-infer-compile/index.html | 4 +- docs/next/man-infer-debug/index.html | 4 +- docs/next/man-infer-explore/index.html | 4 +- docs/next/man-infer-help/index.html | 4 +- docs/next/man-infer-report/index.html | 4 +- docs/next/man-infer-reportdiff/index.html | 4 +- docs/next/man-infer-run/index.html | 4 +- docs/next/man-infer/index.html | 4 +- docs/next/man-pages/index.html | 4 +- .../index.html | 4 +- docs/next/steps-for-ci/index.html | 4 +- docs/next/support/index.html | 4 +- docs/next/versions/index.html | 4 +- .../index.html | 4 +- docs/steps-for-ci/index.html | 4 +- docs/support/index.html | 4 +- docs/versions/index.html | 4 +- index.html | 4 +- man/next/infer-analyze.1.html | 43 ++++++---------- man/next/infer-debug.1.html | 2 +- man/next/infer-report.1.html | 1 - man/next/infer.1.html | 49 ++++++------------- .../Absint/HilExp/AccessExpression/index.html | 4 +- .../Backend/Payloads/Fields/Direct/index.html | 39 +-------------- .../infer/Backend/Payloads/Fields/index.html | 41 ++-------------- odoc/next/infer/Backend/Payloads/index.html | 2 +- odoc/next/infer/Checkers/Uninit/index.html | 4 -- .../Checkers/UninitDomain/Domain/index.html | 2 - .../UninitDomain/MaybeUninitVars/index.html | 7 --- .../Record/argument-1-Domain1/index.html | 2 - .../Record/argument-2-Domain2/index.html | 2 - .../Record/argument-3-Domain3/index.html | 2 - .../Checkers/UninitDomain/Record/index.html | 2 - .../Checkers/UninitDomain/Summary/index.html | 2 - .../Checkers/UninitDomain/VarPair/index.html | 2 - .../infer/Checkers/UninitDomain/index.html | 6 --- odoc/next/infer/Checkers/index.html | 2 +- odoc/next/infer/IBase/Checker/index.html | 2 +- odoc/next/infer/IBase/Config/index.html | 2 +- odoc/next/infer/IBase/IssueType/index.html | 2 +- odoc/next/infer/IR/ProcAttributes/index.html | 2 +- .../infer/Pulselib/PulseArithmetic/index.html | 1 + .../Pulselib/PulseDecompilerExpr/index.html | 2 +- .../infer/Pulselib/PulseDiagnostic/index.html | 2 +- .../infer/Pulselib/PulseFormula/index.html | 2 + .../Textuallib/Textual/VarName/index.html | 2 +- odoc/next/infer/Textuallib/Textual/index.html | 2 +- search/index.html | 4 +- sitemap.xml | 2 +- 211 files changed, 424 insertions(+), 601 deletions(-) delete mode 100644 assets/js/07d14bbd.cb4af53a.js delete mode 100644 assets/js/1c7a9c9f.a953a687.js create mode 100644 assets/js/1c7a9c9f.f02223a9.js create mode 100644 assets/js/7b1f0035.03e05687.js delete mode 100644 assets/js/7b1f0035.f46eb7ff.js create mode 100644 assets/js/935f2afb.37b6f415.js delete mode 100644 assets/js/935f2afb.f9b2dd0c.js create mode 100644 assets/js/c359af60.a486341c.js delete mode 100644 assets/js/c359af60.c62dc728.js create mode 100644 assets/js/ca86781b.656dd032.js delete mode 100644 assets/js/ca86781b.abeae509.js delete mode 100644 assets/js/e9325e77.166166de.js create mode 100644 assets/js/e9325e77.b0fe78fe.js delete mode 100644 assets/js/main.53cbafeb.js create mode 100644 assets/js/main.c71ddf7a.js rename assets/js/{main.53cbafeb.js.LICENSE.txt => main.c71ddf7a.js.LICENSE.txt} (100%) delete mode 100644 assets/js/runtime~main.040defb2.js create mode 100644 assets/js/runtime~main.55292082.js delete mode 100644 docs/next/checker-uninit/index.html delete mode 100644 odoc/next/infer/Checkers/Uninit/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Domain/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/MaybeUninitVars/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Record/argument-1-Domain1/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Record/argument-2-Domain2/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Record/argument-3-Domain3/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Record/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/Summary/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/VarPair/index.html delete mode 100644 odoc/next/infer/Checkers/UninitDomain/index.html diff --git a/404.html b/404.html index d3459e7f29a..d107a39f122 100644 --- a/404.html +++ b/404.html @@ -13,8 +13,8 @@ - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/assets/js/07d14bbd.cb4af53a.js b/assets/js/07d14bbd.cb4af53a.js deleted file mode 100644 index 61776aaa14a..00000000000 --- a/assets/js/07d14bbd.cb4af53a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7848],{4604:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>a});var t=i(7624),s=i(2172);const r={title:"Uninitialized Value",description:"Warns when values are used before having been initialized."},l=void 0,o={id:"checker-uninit",title:"Uninitialized Value",description:"Warns when values are used before having been initialized.",source:"@site/docs/checker-uninit.md",sourceDirName:".",slug:"/checker-uninit",permalink:"/docs/next/checker-uninit",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Uninitialized Value",description:"Warns when values are used before having been initialized."},sidebar:"docs",previous:{title:"Topl",permalink:"/docs/next/checker-topl"},next:{title:"About Infer",permalink:"/docs/next/about-Infer"}},c={},a=[{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"Warns when values are used before having been initialized."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"***DEPRECATED***"})," Uninitialized value checking has moved to Pulse."]}),"\n",(0,t.jsxs)(n.p,{children:["Activate with ",(0,t.jsx)(n.code,{children:"--uninit"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,t.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,t.jsx)(n.li,{children:"Erlang: No"}),"\n",(0,t.jsx)(n.li,{children:"Hack: No"}),"\n",(0,t.jsx)(n.li,{children:"Java: No"}),"\n",(0,t.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,t.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/next/all-issue-types#uninitialized_value",children:"UNINITIALIZED_VALUE"})}),"\n"]})]})}function u(e={}){const{wrapper:n}={...(0,s.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},2172:(e,n,i)=>{i.d(n,{I:()=>o,M:()=>l});var t=i(1504);const s={},r=t.createContext(s);function l(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1c7a9c9f.a953a687.js b/assets/js/1c7a9c9f.a953a687.js deleted file mode 100644 index 44ecfc2782f..00000000000 --- a/assets/js/1c7a9c9f.a953a687.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9792],{9804:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>c,toc:()=>l});var i=t(7624),r=t(2172);const s={title:"Annotation Reachability",description:"Given a pair of source and sink annotation, e.g. `@PerformanceCritical` and `@Expensive`, this checker will warn whenever some method annotated with `@PerformanceCritical` calls, directly or indirectly, another method annotated with `@Expensive`"},a=void 0,c={id:"checker-annotation-reachability",title:"Annotation Reachability",description:"Given a pair of source and sink annotation, e.g. `@PerformanceCritical` and `@Expensive`, this checker will warn whenever some method annotated with `@PerformanceCritical` calls, directly or indirectly, another method annotated with `@Expensive`",source:"@site/docs/checker-annotation-reachability.md",sourceDirName:".",slug:"/checker-annotation-reachability",permalink:"/docs/next/checker-annotation-reachability",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Annotation Reachability",description:"Given a pair of source and sink annotation, e.g. `@PerformanceCritical` and `@Expensive`, this checker will warn whenever some method annotated with `@PerformanceCritical` calls, directly or indirectly, another method annotated with `@Expensive`"},sidebar:"docs",previous:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"},next:{title:"Biabduction",permalink:"/docs/next/checker-biabduction"}},o={},l=[{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Given a pair of source and sink annotation, e.g. ",(0,i.jsx)(n.code,{children:"@PerformanceCritical"})," and ",(0,i.jsx)(n.code,{children:"@Expensive"}),", this checker will warn whenever some method annotated with ",(0,i.jsx)(n.code,{children:"@PerformanceCritical"})," calls, directly or indirectly, another method annotated with ",(0,i.jsx)(n.code,{children:"@Expensive"})]}),"\n",(0,i.jsxs)(n.p,{children:["Activate with ",(0,i.jsx)(n.code,{children:"--annotation-reachability"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,i.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,i.jsx)(n.li,{children:"Erlang: No"}),"\n",(0,i.jsx)(n.li,{children:"Hack: No"}),"\n",(0,i.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,i.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,i.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_expensive_overrides_unannotated",children:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"})}),"\n"]})]})}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,t)=>{t.d(n,{I:()=>c,M:()=>a});var i=t(1504);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1c7a9c9f.f02223a9.js b/assets/js/1c7a9c9f.f02223a9.js new file mode 100644 index 00000000000..c3ca4d0877d --- /dev/null +++ b/assets/js/1c7a9c9f.f02223a9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9792],{9804:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var t=i(7624),s=i(2172);const o={title:"Annotation Reachability",description:"Given pairs of source and sink annotations, e.g. `@A` and `@B`, this checker will warn whenever some method annotated with `@A` calls, directly or indirectly, another method annotated with `@B`. Besides the custom pairs, it is also possible to enable some built-in checks, such as `@PerformanceCritical` reaching `@Expensive` or `@NoAllocation` reaching `new`. See flags starting with `--annotation-reachability`."},a=void 0,c={id:"checker-annotation-reachability",title:"Annotation Reachability",description:"Given pairs of source and sink annotations, e.g. `@A` and `@B`, this checker will warn whenever some method annotated with `@A` calls, directly or indirectly, another method annotated with `@B`. Besides the custom pairs, it is also possible to enable some built-in checks, such as `@PerformanceCritical` reaching `@Expensive` or `@NoAllocation` reaching `new`. See flags starting with `--annotation-reachability`.",source:"@site/docs/checker-annotation-reachability.md",sourceDirName:".",slug:"/checker-annotation-reachability",permalink:"/docs/next/checker-annotation-reachability",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Annotation Reachability",description:"Given pairs of source and sink annotations, e.g. `@A` and `@B`, this checker will warn whenever some method annotated with `@A` calls, directly or indirectly, another method annotated with `@B`. Besides the custom pairs, it is also possible to enable some built-in checks, such as `@PerformanceCritical` reaching `@Expensive` or `@NoAllocation` reaching `new`. See flags starting with `--annotation-reachability`."},sidebar:"docs",previous:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"},next:{title:"Biabduction",permalink:"/docs/next/checker-biabduction"}},r={},l=[{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function h(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",ul:"ul",...(0,s.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["Given pairs of source and sink annotations, e.g. ",(0,t.jsx)(n.code,{children:"@A"})," and ",(0,t.jsx)(n.code,{children:"@B"}),", this checker will warn whenever some method annotated with ",(0,t.jsx)(n.code,{children:"@A"})," calls, directly or indirectly, another method annotated with ",(0,t.jsx)(n.code,{children:"@B"}),". Besides the custom pairs, it is also possible to enable some built-in checks, such as ",(0,t.jsx)(n.code,{children:"@PerformanceCritical"})," reaching ",(0,t.jsx)(n.code,{children:"@Expensive"})," or ",(0,t.jsx)(n.code,{children:"@NoAllocation"})," reaching ",(0,t.jsx)(n.code,{children:"new"}),". See flags starting with ",(0,t.jsx)(n.code,{children:"--annotation-reachability"}),"."]}),"\n",(0,t.jsxs)(n.p,{children:["Activate with ",(0,t.jsx)(n.code,{children:"--annotation-reachability"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,t.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,t.jsx)(n.li,{children:"Erlang: No"}),"\n",(0,t.jsx)(n.li,{children:"Hack: No"}),"\n",(0,t.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,t.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,t.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/docs/next/all-issue-types#checkers_expensive_overrides_unannotated",children:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"})}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,s.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},2172:(e,n,i)=>{i.d(n,{I:()=>c,M:()=>a});var t=i(1504);const s={},o=t.createContext(s);function a(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7b1f0035.03e05687.js b/assets/js/7b1f0035.03e05687.js new file mode 100644 index 00000000000..4478132685a --- /dev/null +++ b/assets/js/7b1f0035.03e05687.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6040],{4584:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var o=t(7624),r=t(2172);const a={id:"about-Infer",title:"About Infer"},i=void 0,s={id:"about-Infer",title:"About Infer",description:"Infer is a static program analyzer for Java, C, C++, Objective-C, and",source:"@site/docs/02-about-infer.md",sourceDirName:".",slug:"/about-Infer",permalink:"/docs/next/about-Infer",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{id:"about-Infer",title:"About Infer"},sidebar:"docs",previous:{title:"Topl",permalink:"/docs/next/checker-topl"},next:{title:"Separation logic and bi-abduction",permalink:"/docs/next/separation-logic-and-bi-abduction"}},c={},u=[];function d(e){const n={a:"a",p:"p",...(0,r.M)(),...e.components};return(0,o.jsxs)(n.p,{children:["Infer is a static program analyzer for Java, C, C++, Objective-C, and\nErlang, written in ",(0,o.jsx)(n.a,{href:"https://ocaml.org/",children:"OCaml"}),". Infer is deployed\nwithin Meta and it is running as part of its Continuous Integration\npipeline to verify select properties of every code modification for a\nlarge range of projects, including the main family of apps such as\nFacebook, Messenger, Instagram, and WhatsApp. Infer is used at a\nnumber of other companies too. Infer can detect deep issues such as\nnull pointer dereferences, data races, and many more, which can\ninvolve reasoning about multiple functions or methods in different\nfiles in the code."]})}function f(e={}){const{wrapper:n}={...(0,r.M)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>s,M:()=>i});var o=t(1504);const r={},a=o.createContext(r);function i(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7b1f0035.f46eb7ff.js b/assets/js/7b1f0035.f46eb7ff.js deleted file mode 100644 index 09887b68528..00000000000 --- a/assets/js/7b1f0035.f46eb7ff.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6040],{4584:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var o=t(7624),r=t(2172);const a={id:"about-Infer",title:"About Infer"},i=void 0,s={id:"about-Infer",title:"About Infer",description:"Infer is a static program analyzer for Java, C, C++, Objective-C, and",source:"@site/docs/02-about-infer.md",sourceDirName:".",slug:"/about-Infer",permalink:"/docs/next/about-Infer",draft:!1,unlisted:!1,tags:[],version:"current",sidebarPosition:2,frontMatter:{id:"about-Infer",title:"About Infer"},sidebar:"docs",previous:{title:"Uninitialized Value",permalink:"/docs/next/checker-uninit"},next:{title:"Separation logic and bi-abduction",permalink:"/docs/next/separation-logic-and-bi-abduction"}},c={},u=[];function d(e){const n={a:"a",p:"p",...(0,r.M)(),...e.components};return(0,o.jsxs)(n.p,{children:["Infer is a static program analyzer for Java, C, C++, Objective-C, and\nErlang, written in ",(0,o.jsx)(n.a,{href:"https://ocaml.org/",children:"OCaml"}),". Infer is deployed\nwithin Meta and it is running as part of its Continuous Integration\npipeline to verify select properties of every code modification for a\nlarge range of projects, including the main family of apps such as\nFacebook, Messenger, Instagram, and WhatsApp. Infer is used at a\nnumber of other companies too. Infer can detect deep issues such as\nnull pointer dereferences, data races, and many more, which can\ninvolve reasoning about multiple functions or methods in different\nfiles in the code."]})}function f(e={}){const{wrapper:n}={...(0,r.M)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>s,M:()=>i});var o=t(1504);const r={},a=o.createContext(r);function i(e){const n=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.37b6f415.js b/assets/js/935f2afb.37b6f415.js new file mode 100644 index 00000000000..d5b1c19abe9 --- /dev/null +++ b/assets/js/935f2afb.37b6f415.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"docs":[{"type":"category","label":"Quick Start","items":[{"type":"link","label":"Getting started with Infer","href":"/docs/next/getting-started","docId":"getting-started","unlisted":false},{"type":"link","label":"Hello, World!","href":"/docs/next/hello-world","docId":"hello-world","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"User Guide","items":[{"type":"link","label":"Infer workflow","href":"/docs/next/infer-workflow","docId":"infer-workflow","unlisted":false},{"type":"link","label":"Analyzing apps or projects","href":"/docs/next/analyzing-apps-or-projects","docId":"analyzing-apps-or-projects","unlisted":false},{"type":"link","label":"Recommended flow for CI","href":"/docs/next/steps-for-ci","docId":"steps-for-ci","unlisted":false},{"type":"category","label":"Infer Manuals","items":[{"type":"link","label":"infer","href":"/docs/next/man-infer","docId":"man-infer","unlisted":false},{"type":"link","label":"infer analyze","href":"/docs/next/man-infer-analyze","docId":"man-infer-analyze","unlisted":false},{"type":"link","label":"infer capture","href":"/docs/next/man-infer-capture","docId":"man-infer-capture","unlisted":false},{"type":"link","label":"infer compile","href":"/docs/next/man-infer-compile","docId":"man-infer-compile","unlisted":false},{"type":"link","label":"infer debug","href":"/docs/next/man-infer-debug","docId":"man-infer-debug","unlisted":false},{"type":"link","label":"infer explore","href":"/docs/next/man-infer-explore","docId":"man-infer-explore","unlisted":false},{"type":"link","label":"infer help","href":"/docs/next/man-infer-help","docId":"man-infer-help","unlisted":false},{"type":"link","label":"infer report","href":"/docs/next/man-infer-report","docId":"man-infer-report","unlisted":false},{"type":"link","label":"infer reportdiff","href":"/docs/next/man-infer-reportdiff","docId":"man-infer-reportdiff","unlisted":false},{"type":"link","label":"infer run","href":"/docs/next/man-infer-run","docId":"man-infer-run","unlisted":false}],"collapsed":true,"collapsible":true}],"collapsed":true,"collapsible":true},{"type":"category","label":"Analyses and Issue Types","items":[{"type":"link","label":"List of all checkers","href":"/docs/next/all-checkers","docId":"all-checkers","unlisted":false},{"type":"link","label":"List of all issue types","href":"/docs/next/all-issue-types","docId":"all-issue-types","unlisted":false},{"type":"link","label":"Annotation Reachability","href":"/docs/next/checker-annotation-reachability","docId":"checker-annotation-reachability","unlisted":false},{"type":"link","label":"Biabduction","href":"/docs/next/checker-biabduction","docId":"checker-biabduction","unlisted":false},{"type":"link","label":"Buffer Overrun Analysis (InferBO)","href":"/docs/next/checker-bufferoverrun","docId":"checker-bufferoverrun","unlisted":false},{"type":"link","label":"Config Impact Analysis","href":"/docs/next/checker-config-impact-analysis","docId":"checker-config-impact-analysis","unlisted":false},{"type":"link","label":"Cost: Complexity Analysis","href":"/docs/next/checker-cost","docId":"checker-cost","unlisted":false},{"type":"link","label":"Datalog-based points-to analysis","href":"/docs/next/checker-datalog","docId":"checker-datalog","unlisted":false},{"type":"link","label":"Fragment Retains View","href":"/docs/next/checker-fragment-retains-view","docId":"checker-fragment-retains-view","unlisted":false},{"type":"link","label":"Impurity","href":"/docs/next/checker-impurity","docId":"checker-impurity","unlisted":false},{"type":"link","label":"Inefficient keySet Iterator","href":"/docs/next/checker-inefficient-keyset-iterator","docId":"checker-inefficient-keyset-iterator","unlisted":false},{"type":"link","label":"Litho \\"Required Props\\"","href":"/docs/next/checker-litho-required-props","docId":"checker-litho-required-props","unlisted":false},{"type":"link","label":"Liveness","href":"/docs/next/checker-liveness","docId":"checker-liveness","unlisted":false},{"type":"link","label":"Loop Hoisting","href":"/docs/next/checker-loop-hoisting","docId":"checker-loop-hoisting","unlisted":false},{"type":"link","label":"Parameter Not Null Checked","href":"/docs/next/checker-parameter-not-null-checked","docId":"checker-parameter-not-null-checked","unlisted":false},{"type":"link","label":"`printf()` Argument Types","href":"/docs/next/checker-printf-args","docId":"checker-printf-args","unlisted":false},{"type":"link","label":"Pulse","href":"/docs/next/checker-pulse","docId":"checker-pulse","unlisted":false},{"type":"link","label":"Purity","href":"/docs/next/checker-purity","docId":"checker-purity","unlisted":false},{"type":"link","label":"Quandary","href":"/docs/next/checker-quandary","docId":"checker-quandary","unlisted":false},{"type":"link","label":"RacerD","href":"/docs/next/checker-racerd","docId":"checker-racerd","unlisted":false},{"type":"link","label":"Resource Leak Lab Exercise","href":"/docs/next/checker-resource-leak-lab","docId":"checker-resource-leak-lab","unlisted":false},{"type":"link","label":"Scope Leakage","href":"/docs/next/checker-scope-leakage","docId":"checker-scope-leakage","unlisted":false},{"type":"link","label":"Static Initialization Order Fiasco","href":"/docs/next/checker-siof","docId":"checker-siof","unlisted":false},{"type":"link","label":"SIL validation","href":"/docs/next/checker-sil-validation","docId":"checker-sil-validation","unlisted":false},{"type":"link","label":"Lineage","href":"/docs/next/checker-lineage","docId":"checker-lineage","unlisted":false},{"type":"link","label":"Self in Block","href":"/docs/next/checker-self-in-block","docId":"checker-self-in-block","unlisted":false},{"type":"link","label":"Starvation","href":"/docs/next/checker-starvation","docId":"checker-starvation","unlisted":false},{"type":"link","label":"Topl","href":"/docs/next/checker-topl","docId":"checker-topl","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Foundations","items":[{"type":"link","label":"About Infer","href":"/docs/next/about-Infer","docId":"about-Infer","unlisted":false},{"type":"link","label":"Separation logic and bi-abduction","href":"/docs/next/separation-logic-and-bi-abduction","docId":"separation-logic-and-bi-abduction","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Contribute","items":[{"type":"link","label":"Building checkers with the Infer.AI framework","href":"/docs/next/absint-framework","docId":"absint-framework","unlisted":false},{"type":"link","label":"Infer Internal OCaml Modules API","href":"/docs/next/internal-API","docId":"internal-API","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Versions","items":[{"type":"link","label":"Documentation Versions","href":"/docs/next/versions","docId":"versions","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"about-Infer":{"id":"about-Infer","title":"About Infer","description":"Infer is a static program analyzer for Java, C, C++, Objective-C, and","sidebar":"docs"},"absint-framework":{"id":"absint-framework","title":"Building checkers with the Infer.AI framework","description":"Infer.AI is a framework for quickly developing abstract interpretation-based","sidebar":"docs"},"all-checkers":{"id":"all-checkers","title":"List of all checkers","description":"Here is an overview of the checkers currently available in Infer.","sidebar":"docs"},"all-issue-types":{"id":"all-issue-types","title":"List of all issue types","description":"Here is an overview of the issue types currently reported by Infer.","sidebar":"docs"},"analyzing-apps-or-projects":{"id":"analyzing-apps-or-projects","title":"Analyzing apps or projects","description":"To analyze files with Infer you can use the compilers javac and clang. You","sidebar":"docs"},"checker-annotation-reachability":{"id":"checker-annotation-reachability","title":"Annotation Reachability","description":"Given pairs of source and sink annotations, e.g. `@A` and `@B`, this checker will warn whenever some method annotated with `@A` calls, directly or indirectly, another method annotated with `@B`. Besides the custom pairs, it is also possible to enable some built-in checks, such as `@PerformanceCritical` reaching `@Expensive` or `@NoAllocation` reaching `new`. See flags starting with `--annotation-reachability`.","sidebar":"docs"},"checker-biabduction":{"id":"checker-biabduction","title":"Biabduction","description":"This analysis deals with a range of issues, many linked to memory safety.","sidebar":"docs"},"checker-bufferoverrun":{"id":"checker-bufferoverrun","title":"Buffer Overrun Analysis (InferBO)","description":"InferBO is a detector for out-of-bounds array accesses.","sidebar":"docs"},"checker-config-impact-analysis":{"id":"checker-config-impact-analysis","title":"Config Impact Analysis","description":"[EXPERIMENTAL] Collects function that are called without config checks.","sidebar":"docs"},"checker-cost":{"id":"checker-cost","title":"Cost: Complexity Analysis","description":"Computes the asymptotic complexity of functions with respect to execution cost or other user defined resources. Can be used to detect changes in the complexity with `infer reportdiff`.","sidebar":"docs"},"checker-datalog":{"id":"checker-datalog","title":"Datalog-based points-to analysis","description":"Experimental datalog-based points-to analysis.","sidebar":"docs"},"checker-fragment-retains-view":{"id":"checker-fragment-retains-view","title":"Fragment Retains View","description":"Detects when Android fragments are not explicitly nullified before becoming unreachable.","sidebar":"docs"},"checker-impurity":{"id":"checker-impurity","title":"Impurity","description":"Detects functions with potential side-effects. Same as \\"purity\\", but implemented on top of Pulse.","sidebar":"docs"},"checker-inefficient-keyset-iterator":{"id":"checker-inefficient-keyset-iterator","title":"Inefficient keySet Iterator","description":"Check for inefficient uses of iterators that iterate on keys then lookup their values, instead of iterating on key-value pairs directly.","sidebar":"docs"},"checker-lineage":{"id":"checker-lineage","title":"Lineage","description":"Computes a dataflow graph","sidebar":"docs"},"checker-litho-required-props":{"id":"checker-litho-required-props","title":"Litho \\"Required Props\\"","description":"Checks that all non-optional `@Prop`s have been specified when constructing Litho components.","sidebar":"docs"},"checker-liveness":{"id":"checker-liveness","title":"Liveness","description":"Detection of dead stores and unused variables.","sidebar":"docs"},"checker-loop-hoisting":{"id":"checker-loop-hoisting","title":"Loop Hoisting","description":"Detect opportunities to hoist function calls that are invariant outside of loop bodies for efficiency.","sidebar":"docs"},"checker-parameter-not-null-checked":{"id":"checker-parameter-not-null-checked","title":"Parameter Not Null Checked","description":"An Objective-C-specific analysis to detect when a block parameter is used before being checked for null first.","sidebar":"docs"},"checker-printf-args":{"id":"checker-printf-args","title":"`printf()` Argument Types","description":"Detect mismatches between the Java `printf` format strings and the argument types For example, this checker will warn about the type error in `printf(\\"Hello %d\\", \\"world\\")`","sidebar":"docs"},"checker-pulse":{"id":"checker-pulse","title":"Pulse","description":"General-purpose memory and value analysis engine.","sidebar":"docs"},"checker-purity":{"id":"checker-purity","title":"Purity","description":"Detects pure (side-effect-free) functions. A different implementation of \\"impurity\\".","sidebar":"docs"},"checker-quandary":{"id":"checker-quandary","title":"Quandary","description":"The Quandary taint analysis detects flows of values between sources and sinks, except if the value went through a \\"sanitizer\\". In addition to some defaults, users can specify their own sources, sinks, and sanitizers functions.","sidebar":"docs"},"checker-racerd":{"id":"checker-racerd","title":"RacerD","description":"Thread safety analysis.","sidebar":"docs"},"checker-resource-leak-lab":{"id":"checker-resource-leak-lab","title":"Resource Leak Lab Exercise","description":"Toy checker for the \\"resource leak\\" write-your-own-checker exercise.","sidebar":"docs"},"checker-scope-leakage":{"id":"checker-scope-leakage","title":"Scope Leakage","description":"The Java/Kotlin checker takes into account a set of \\"scope\\" annotations and a must-not-hold relation over the scopes. The checker raises an alarm if there exists a field access path from object A to object B, with respective scopes SA and SB, such that must-not-hold(SA, SB).","sidebar":"docs"},"checker-self-in-block":{"id":"checker-self-in-block","title":"Self in Block","description":"An Objective-C-specific analysis to detect when a block captures `self`.","sidebar":"docs"},"checker-sil-validation":{"id":"checker-sil-validation","title":"SIL validation","description":"This checker validates that all SIL instructions in all procedure bodies conform to a (front-end specific) subset of SIL.","sidebar":"docs"},"checker-siof":{"id":"checker-siof","title":"Static Initialization Order Fiasco","description":"Catches Static Initialization Order Fiascos in C++, that can lead to subtle, compiler-version-dependent errors.","sidebar":"docs"},"checker-starvation":{"id":"checker-starvation","title":"Starvation","description":"Detect various kinds of situations when no progress is being made because of concurrency errors.","sidebar":"docs"},"checker-topl":{"id":"checker-topl","title":"Topl","description":"Detect errors based on user-provided state machines describing temporal properties over multiple objects.","sidebar":"docs"},"getting-started":{"id":"getting-started","title":"Getting started with Infer","description":"Get Infer","sidebar":"docs"},"hello-world":{"id":"hello-world","title":"Hello, World!","description":"Follow the instructions in this page to try Infer on a few small examples. You","sidebar":"docs"},"infer-workflow":{"id":"infer-workflow","title":"Infer workflow","description":"This page documents several ways of running Infer, that you can adapt to your","sidebar":"docs"},"internal-API":{"id":"internal-API","title":"Infer Internal OCaml Modules API","description":"Browse the generated documentation for Infer\'s OCaml code here.","sidebar":"docs"},"man-infer":{"id":"man-infer","title":"infer","description":"","sidebar":"docs"},"man-infer-analyze":{"id":"man-infer-analyze","title":"infer analyze","description":"","sidebar":"docs"},"man-infer-capture":{"id":"man-infer-capture","title":"infer capture","description":"","sidebar":"docs"},"man-infer-compile":{"id":"man-infer-compile","title":"infer compile","description":"","sidebar":"docs"},"man-infer-debug":{"id":"man-infer-debug","title":"infer debug","description":"","sidebar":"docs"},"man-infer-explore":{"id":"man-infer-explore","title":"infer explore","description":"","sidebar":"docs"},"man-infer-help":{"id":"man-infer-help","title":"infer help","description":"","sidebar":"docs"},"man-infer-report":{"id":"man-infer-report","title":"infer report","description":"","sidebar":"docs"},"man-infer-reportdiff":{"id":"man-infer-reportdiff","title":"infer reportdiff","description":"","sidebar":"docs"},"man-infer-run":{"id":"man-infer-run","title":"infer run","description":"","sidebar":"docs"},"man-pages":{"id":"man-pages","title":"Infer Manuals","description":"Here are the man pages for all the infer commands:"},"separation-logic-and-bi-abduction":{"id":"separation-logic-and-bi-abduction","title":"Separation logic and bi-abduction","description":"- Separation logic","sidebar":"docs"},"steps-for-ci":{"id":"steps-for-ci","title":"Recommended flow for CI","description":"The recommended flow for CI integration is to determine the modified files, and","sidebar":"docs"},"support":{"id":"support","title":"Infer | Need help?","description":"Need help?"},"versions":{"id":"versions","title":"Documentation Versions","description":"Browse the documentation for different versions:","sidebar":"docs"}}}')}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.f9b2dd0c.js b/assets/js/935f2afb.f9b2dd0c.js deleted file mode 100644 index e8cbaa45131..00000000000 --- a/assets/js/935f2afb.f9b2dd0c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"docs":[{"type":"category","label":"Quick Start","items":[{"type":"link","label":"Getting started with Infer","href":"/docs/next/getting-started","docId":"getting-started","unlisted":false},{"type":"link","label":"Hello, World!","href":"/docs/next/hello-world","docId":"hello-world","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"User Guide","items":[{"type":"link","label":"Infer workflow","href":"/docs/next/infer-workflow","docId":"infer-workflow","unlisted":false},{"type":"link","label":"Analyzing apps or projects","href":"/docs/next/analyzing-apps-or-projects","docId":"analyzing-apps-or-projects","unlisted":false},{"type":"link","label":"Recommended flow for CI","href":"/docs/next/steps-for-ci","docId":"steps-for-ci","unlisted":false},{"type":"category","label":"Infer Manuals","items":[{"type":"link","label":"infer","href":"/docs/next/man-infer","docId":"man-infer","unlisted":false},{"type":"link","label":"infer analyze","href":"/docs/next/man-infer-analyze","docId":"man-infer-analyze","unlisted":false},{"type":"link","label":"infer capture","href":"/docs/next/man-infer-capture","docId":"man-infer-capture","unlisted":false},{"type":"link","label":"infer compile","href":"/docs/next/man-infer-compile","docId":"man-infer-compile","unlisted":false},{"type":"link","label":"infer debug","href":"/docs/next/man-infer-debug","docId":"man-infer-debug","unlisted":false},{"type":"link","label":"infer explore","href":"/docs/next/man-infer-explore","docId":"man-infer-explore","unlisted":false},{"type":"link","label":"infer help","href":"/docs/next/man-infer-help","docId":"man-infer-help","unlisted":false},{"type":"link","label":"infer report","href":"/docs/next/man-infer-report","docId":"man-infer-report","unlisted":false},{"type":"link","label":"infer reportdiff","href":"/docs/next/man-infer-reportdiff","docId":"man-infer-reportdiff","unlisted":false},{"type":"link","label":"infer run","href":"/docs/next/man-infer-run","docId":"man-infer-run","unlisted":false}],"collapsed":true,"collapsible":true}],"collapsed":true,"collapsible":true},{"type":"category","label":"Analyses and Issue Types","items":[{"type":"link","label":"List of all checkers","href":"/docs/next/all-checkers","docId":"all-checkers","unlisted":false},{"type":"link","label":"List of all issue types","href":"/docs/next/all-issue-types","docId":"all-issue-types","unlisted":false},{"type":"link","label":"Annotation Reachability","href":"/docs/next/checker-annotation-reachability","docId":"checker-annotation-reachability","unlisted":false},{"type":"link","label":"Biabduction","href":"/docs/next/checker-biabduction","docId":"checker-biabduction","unlisted":false},{"type":"link","label":"Buffer Overrun Analysis (InferBO)","href":"/docs/next/checker-bufferoverrun","docId":"checker-bufferoverrun","unlisted":false},{"type":"link","label":"Config Impact Analysis","href":"/docs/next/checker-config-impact-analysis","docId":"checker-config-impact-analysis","unlisted":false},{"type":"link","label":"Cost: Complexity Analysis","href":"/docs/next/checker-cost","docId":"checker-cost","unlisted":false},{"type":"link","label":"Datalog-based points-to analysis","href":"/docs/next/checker-datalog","docId":"checker-datalog","unlisted":false},{"type":"link","label":"Fragment Retains View","href":"/docs/next/checker-fragment-retains-view","docId":"checker-fragment-retains-view","unlisted":false},{"type":"link","label":"Impurity","href":"/docs/next/checker-impurity","docId":"checker-impurity","unlisted":false},{"type":"link","label":"Inefficient keySet Iterator","href":"/docs/next/checker-inefficient-keyset-iterator","docId":"checker-inefficient-keyset-iterator","unlisted":false},{"type":"link","label":"Litho \\"Required Props\\"","href":"/docs/next/checker-litho-required-props","docId":"checker-litho-required-props","unlisted":false},{"type":"link","label":"Liveness","href":"/docs/next/checker-liveness","docId":"checker-liveness","unlisted":false},{"type":"link","label":"Loop Hoisting","href":"/docs/next/checker-loop-hoisting","docId":"checker-loop-hoisting","unlisted":false},{"type":"link","label":"Parameter Not Null Checked","href":"/docs/next/checker-parameter-not-null-checked","docId":"checker-parameter-not-null-checked","unlisted":false},{"type":"link","label":"`printf()` Argument Types","href":"/docs/next/checker-printf-args","docId":"checker-printf-args","unlisted":false},{"type":"link","label":"Pulse","href":"/docs/next/checker-pulse","docId":"checker-pulse","unlisted":false},{"type":"link","label":"Purity","href":"/docs/next/checker-purity","docId":"checker-purity","unlisted":false},{"type":"link","label":"Quandary","href":"/docs/next/checker-quandary","docId":"checker-quandary","unlisted":false},{"type":"link","label":"RacerD","href":"/docs/next/checker-racerd","docId":"checker-racerd","unlisted":false},{"type":"link","label":"Resource Leak Lab Exercise","href":"/docs/next/checker-resource-leak-lab","docId":"checker-resource-leak-lab","unlisted":false},{"type":"link","label":"Scope Leakage","href":"/docs/next/checker-scope-leakage","docId":"checker-scope-leakage","unlisted":false},{"type":"link","label":"Static Initialization Order Fiasco","href":"/docs/next/checker-siof","docId":"checker-siof","unlisted":false},{"type":"link","label":"SIL validation","href":"/docs/next/checker-sil-validation","docId":"checker-sil-validation","unlisted":false},{"type":"link","label":"Lineage","href":"/docs/next/checker-lineage","docId":"checker-lineage","unlisted":false},{"type":"link","label":"Self in Block","href":"/docs/next/checker-self-in-block","docId":"checker-self-in-block","unlisted":false},{"type":"link","label":"Starvation","href":"/docs/next/checker-starvation","docId":"checker-starvation","unlisted":false},{"type":"link","label":"Topl","href":"/docs/next/checker-topl","docId":"checker-topl","unlisted":false},{"type":"link","label":"Uninitialized Value","href":"/docs/next/checker-uninit","docId":"checker-uninit","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Foundations","items":[{"type":"link","label":"About Infer","href":"/docs/next/about-Infer","docId":"about-Infer","unlisted":false},{"type":"link","label":"Separation logic and bi-abduction","href":"/docs/next/separation-logic-and-bi-abduction","docId":"separation-logic-and-bi-abduction","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Contribute","items":[{"type":"link","label":"Building checkers with the Infer.AI framework","href":"/docs/next/absint-framework","docId":"absint-framework","unlisted":false},{"type":"link","label":"Infer Internal OCaml Modules API","href":"/docs/next/internal-API","docId":"internal-API","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Versions","items":[{"type":"link","label":"Documentation Versions","href":"/docs/next/versions","docId":"versions","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"about-Infer":{"id":"about-Infer","title":"About Infer","description":"Infer is a static program analyzer for Java, C, C++, Objective-C, and","sidebar":"docs"},"absint-framework":{"id":"absint-framework","title":"Building checkers with the Infer.AI framework","description":"Infer.AI is a framework for quickly developing abstract interpretation-based","sidebar":"docs"},"all-checkers":{"id":"all-checkers","title":"List of all checkers","description":"Here is an overview of the checkers currently available in Infer.","sidebar":"docs"},"all-issue-types":{"id":"all-issue-types","title":"List of all issue types","description":"Here is an overview of the issue types currently reported by Infer.","sidebar":"docs"},"analyzing-apps-or-projects":{"id":"analyzing-apps-or-projects","title":"Analyzing apps or projects","description":"To analyze files with Infer you can use the compilers javac and clang. You","sidebar":"docs"},"checker-annotation-reachability":{"id":"checker-annotation-reachability","title":"Annotation Reachability","description":"Given a pair of source and sink annotation, e.g. `@PerformanceCritical` and `@Expensive`, this checker will warn whenever some method annotated with `@PerformanceCritical` calls, directly or indirectly, another method annotated with `@Expensive`","sidebar":"docs"},"checker-biabduction":{"id":"checker-biabduction","title":"Biabduction","description":"This analysis deals with a range of issues, many linked to memory safety.","sidebar":"docs"},"checker-bufferoverrun":{"id":"checker-bufferoverrun","title":"Buffer Overrun Analysis (InferBO)","description":"InferBO is a detector for out-of-bounds array accesses.","sidebar":"docs"},"checker-config-impact-analysis":{"id":"checker-config-impact-analysis","title":"Config Impact Analysis","description":"[EXPERIMENTAL] Collects function that are called without config checks.","sidebar":"docs"},"checker-cost":{"id":"checker-cost","title":"Cost: Complexity Analysis","description":"Computes the asymptotic complexity of functions with respect to execution cost or other user defined resources. Can be used to detect changes in the complexity with `infer reportdiff`.","sidebar":"docs"},"checker-datalog":{"id":"checker-datalog","title":"Datalog-based points-to analysis","description":"Experimental datalog-based points-to analysis.","sidebar":"docs"},"checker-fragment-retains-view":{"id":"checker-fragment-retains-view","title":"Fragment Retains View","description":"Detects when Android fragments are not explicitly nullified before becoming unreachable.","sidebar":"docs"},"checker-impurity":{"id":"checker-impurity","title":"Impurity","description":"Detects functions with potential side-effects. Same as \\"purity\\", but implemented on top of Pulse.","sidebar":"docs"},"checker-inefficient-keyset-iterator":{"id":"checker-inefficient-keyset-iterator","title":"Inefficient keySet Iterator","description":"Check for inefficient uses of iterators that iterate on keys then lookup their values, instead of iterating on key-value pairs directly.","sidebar":"docs"},"checker-lineage":{"id":"checker-lineage","title":"Lineage","description":"Computes a dataflow graph","sidebar":"docs"},"checker-litho-required-props":{"id":"checker-litho-required-props","title":"Litho \\"Required Props\\"","description":"Checks that all non-optional `@Prop`s have been specified when constructing Litho components.","sidebar":"docs"},"checker-liveness":{"id":"checker-liveness","title":"Liveness","description":"Detection of dead stores and unused variables.","sidebar":"docs"},"checker-loop-hoisting":{"id":"checker-loop-hoisting","title":"Loop Hoisting","description":"Detect opportunities to hoist function calls that are invariant outside of loop bodies for efficiency.","sidebar":"docs"},"checker-parameter-not-null-checked":{"id":"checker-parameter-not-null-checked","title":"Parameter Not Null Checked","description":"An Objective-C-specific analysis to detect when a block parameter is used before being checked for null first.","sidebar":"docs"},"checker-printf-args":{"id":"checker-printf-args","title":"`printf()` Argument Types","description":"Detect mismatches between the Java `printf` format strings and the argument types For example, this checker will warn about the type error in `printf(\\"Hello %d\\", \\"world\\")`","sidebar":"docs"},"checker-pulse":{"id":"checker-pulse","title":"Pulse","description":"General-purpose memory and value analysis engine.","sidebar":"docs"},"checker-purity":{"id":"checker-purity","title":"Purity","description":"Detects pure (side-effect-free) functions. A different implementation of \\"impurity\\".","sidebar":"docs"},"checker-quandary":{"id":"checker-quandary","title":"Quandary","description":"The Quandary taint analysis detects flows of values between sources and sinks, except if the value went through a \\"sanitizer\\". In addition to some defaults, users can specify their own sources, sinks, and sanitizers functions.","sidebar":"docs"},"checker-racerd":{"id":"checker-racerd","title":"RacerD","description":"Thread safety analysis.","sidebar":"docs"},"checker-resource-leak-lab":{"id":"checker-resource-leak-lab","title":"Resource Leak Lab Exercise","description":"Toy checker for the \\"resource leak\\" write-your-own-checker exercise.","sidebar":"docs"},"checker-scope-leakage":{"id":"checker-scope-leakage","title":"Scope Leakage","description":"The Java/Kotlin checker takes into account a set of \\"scope\\" annotations and a must-not-hold relation over the scopes. The checker raises an alarm if there exists a field access path from object A to object B, with respective scopes SA and SB, such that must-not-hold(SA, SB).","sidebar":"docs"},"checker-self-in-block":{"id":"checker-self-in-block","title":"Self in Block","description":"An Objective-C-specific analysis to detect when a block captures `self`.","sidebar":"docs"},"checker-sil-validation":{"id":"checker-sil-validation","title":"SIL validation","description":"This checker validates that all SIL instructions in all procedure bodies conform to a (front-end specific) subset of SIL.","sidebar":"docs"},"checker-siof":{"id":"checker-siof","title":"Static Initialization Order Fiasco","description":"Catches Static Initialization Order Fiascos in C++, that can lead to subtle, compiler-version-dependent errors.","sidebar":"docs"},"checker-starvation":{"id":"checker-starvation","title":"Starvation","description":"Detect various kinds of situations when no progress is being made because of concurrency errors.","sidebar":"docs"},"checker-topl":{"id":"checker-topl","title":"Topl","description":"Detect errors based on user-provided state machines describing temporal properties over multiple objects.","sidebar":"docs"},"checker-uninit":{"id":"checker-uninit","title":"Uninitialized Value","description":"Warns when values are used before having been initialized.","sidebar":"docs"},"getting-started":{"id":"getting-started","title":"Getting started with Infer","description":"Get Infer","sidebar":"docs"},"hello-world":{"id":"hello-world","title":"Hello, World!","description":"Follow the instructions in this page to try Infer on a few small examples. You","sidebar":"docs"},"infer-workflow":{"id":"infer-workflow","title":"Infer workflow","description":"This page documents several ways of running Infer, that you can adapt to your","sidebar":"docs"},"internal-API":{"id":"internal-API","title":"Infer Internal OCaml Modules API","description":"Browse the generated documentation for Infer\'s OCaml code here.","sidebar":"docs"},"man-infer":{"id":"man-infer","title":"infer","description":"","sidebar":"docs"},"man-infer-analyze":{"id":"man-infer-analyze","title":"infer analyze","description":"","sidebar":"docs"},"man-infer-capture":{"id":"man-infer-capture","title":"infer capture","description":"","sidebar":"docs"},"man-infer-compile":{"id":"man-infer-compile","title":"infer compile","description":"","sidebar":"docs"},"man-infer-debug":{"id":"man-infer-debug","title":"infer debug","description":"","sidebar":"docs"},"man-infer-explore":{"id":"man-infer-explore","title":"infer explore","description":"","sidebar":"docs"},"man-infer-help":{"id":"man-infer-help","title":"infer help","description":"","sidebar":"docs"},"man-infer-report":{"id":"man-infer-report","title":"infer report","description":"","sidebar":"docs"},"man-infer-reportdiff":{"id":"man-infer-reportdiff","title":"infer reportdiff","description":"","sidebar":"docs"},"man-infer-run":{"id":"man-infer-run","title":"infer run","description":"","sidebar":"docs"},"man-pages":{"id":"man-pages","title":"Infer Manuals","description":"Here are the man pages for all the infer commands:"},"separation-logic-and-bi-abduction":{"id":"separation-logic-and-bi-abduction","title":"Separation logic and bi-abduction","description":"- Separation logic","sidebar":"docs"},"steps-for-ci":{"id":"steps-for-ci","title":"Recommended flow for CI","description":"The recommended flow for CI integration is to determine the modified files, and","sidebar":"docs"},"support":{"id":"support","title":"Infer | Need help?","description":"Need help?"},"versions":{"id":"versions","title":"Documentation Versions","description":"Browse the documentation for different versions:","sidebar":"docs"}}}')}}]); \ No newline at end of file diff --git a/assets/js/c359af60.a486341c.js b/assets/js/c359af60.a486341c.js new file mode 100644 index 00000000000..ce5d759eb9e --- /dev/null +++ b/assets/js/c359af60.a486341c.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:"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.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:"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:"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 deleted file mode 100644 index 78f2af9ac17..00000000000 --- a/assets/js/c359af60.c62dc728.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_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/ca86781b.656dd032.js b/assets/js/ca86781b.656dd032.js new file mode 100644 index 00000000000..110cf2803fd --- /dev/null +++ b/assets/js/ca86781b.656dd032.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4856],{3916:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=n(7624),s=n(2172);const t={title:"List of all checkers",hide_table_of_contents:!0},o=void 0,a={id:"all-checkers",title:"List of all checkers",description:"Here is an overview of the checkers currently available in Infer.",source:"@site/docs/all-checkers.md",sourceDirName:".",slug:"/all-checkers",permalink:"/docs/next/all-checkers",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"List of all checkers",hide_table_of_contents:!0},sidebar:"docs",previous:{title:"infer run",permalink:"/docs/next/man-infer-run"},next:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"}},c={},l=[{value:"Annotation Reachability",id:"annotation-reachability",level:2},{value:"Biabduction",id:"biabduction",level:2},{value:"Buffer Overrun Analysis (InferBO)",id:"buffer-overrun-analysis-inferbo",level:2},{value:"Config Impact Analysis",id:"config-impact-analysis",level:2},{value:"Cost: Complexity Analysis",id:"cost-complexity-analysis",level:2},{value:"Datalog-based points-to analysis",id:"datalog-based-points-to-analysis",level:2},{value:"Fragment Retains View",id:"fragment-retains-view",level:2},{value:"Impurity",id:"impurity",level:2},{value:"Inefficient keySet Iterator",id:"inefficient-keyset-iterator",level:2},{value:"Litho "Required Props"",id:"litho-required-props",level:2},{value:"Liveness",id:"liveness",level:2},{value:"Loop Hoisting",id:"loop-hoisting",level:2},{value:"Parameter Not Null Checked",id:"parameter-not-null-checked",level:2},{value:"printf() Argument Types",id:"printf-argument-types",level:2},{value:"Pulse",id:"pulse",level:2},{value:"Purity",id:"purity",level:2},{value:"Quandary",id:"quandary",level:2},{value:"RacerD",id:"racerd",level:2},{value:"Resource Leak Lab Exercise",id:"resource-leak-lab-exercise",level:2},{value:"Scope Leakage",id:"scope-leakage",level:2},{value:"Static Initialization Order Fiasco",id:"static-initialization-order-fiasco",level:2},{value:"SIL validation",id:"sil-validation",level:2},{value:"Lineage",id:"lineage",level:2},{value:"Self in Block",id:"self-in-block",level:2},{value:"Starvation",id:"starvation",level:2},{value:"Topl",id:"topl",level:2}];function d(e){const i={a:"a",code:"code",h2:"h2",p:"p",strong:"strong",...(0,s.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.p,{children:"Here is an overview of the checkers currently available in Infer."}),"\n",(0,r.jsx)(i.h2,{id:"annotation-reachability",children:"Annotation Reachability"}),"\n",(0,r.jsxs)(i.p,{children:["Given pairs of source and sink annotations, e.g. ",(0,r.jsx)(i.code,{children:"@A"})," and ",(0,r.jsx)(i.code,{children:"@B"}),", this checker will warn whenever some method annotated with ",(0,r.jsx)(i.code,{children:"@A"})," calls, directly or indirectly, another method annotated with ",(0,r.jsx)(i.code,{children:"@B"}),". Besides the custom pairs, it is also possible to enable some built-in checks, such as ",(0,r.jsx)(i.code,{children:"@PerformanceCritical"})," reaching ",(0,r.jsx)(i.code,{children:"@Expensive"})," or ",(0,r.jsx)(i.code,{children:"@NoAllocation"})," reaching ",(0,r.jsx)(i.code,{children:"new"}),". See flags starting with ",(0,r.jsx)(i.code,{children:"--annotation-reachability"}),"."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-annotation-reachability",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"biabduction",children:"Biabduction"}),"\n",(0,r.jsx)(i.p,{children:"This analysis deals with a range of issues, many linked to memory safety."}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," This has been replaced by Pulse and will be removed in the next release."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-biabduction",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"buffer-overrun-analysis-inferbo",children:"Buffer Overrun Analysis (InferBO)"}),"\n",(0,r.jsx)(i.p,{children:"InferBO is a detector for out-of-bounds array accesses."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-bufferoverrun",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"config-impact-analysis",children:"Config Impact Analysis"}),"\n",(0,r.jsx)(i.p,{children:"[EXPERIMENTAL] Collects function that are called without config checks."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-config-impact-analysis",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"cost-complexity-analysis",children:"Cost: Complexity Analysis"}),"\n",(0,r.jsxs)(i.p,{children:["Computes the asymptotic complexity of functions with respect to execution cost or other user defined resources. Can be used to detect changes in the complexity with ",(0,r.jsx)(i.code,{children:"infer reportdiff"}),"."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-cost",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"datalog-based-points-to-analysis",children:"Datalog-based points-to analysis"}),"\n",(0,r.jsx)(i.p,{children:"Experimental datalog-based points-to analysis."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-datalog",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"fragment-retains-view",children:"Fragment Retains View"}),"\n",(0,r.jsx)(i.p,{children:"Detects when Android fragments are not explicitly nullified before becoming unreachable."}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Unmaintained due to poor precision."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-fragment-retains-view",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"impurity",children:"Impurity"}),"\n",(0,r.jsx)(i.p,{children:'Detects functions with potential side-effects. Same as "purity", but implemented on top of Pulse.'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-impurity",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"inefficient-keyset-iterator",children:"Inefficient keySet Iterator"}),"\n",(0,r.jsx)(i.p,{children:"Check for inefficient uses of iterators that iterate on keys then lookup their values, instead of iterating on key-value pairs directly."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"litho-required-props",children:'Litho "Required Props"'}),"\n",(0,r.jsxs)(i.p,{children:["Checks that all non-optional ",(0,r.jsx)(i.code,{children:"@Prop"}),"s have been specified when constructing Litho components."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-litho-required-props",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"liveness",children:"Liveness"}),"\n",(0,r.jsx)(i.p,{children:"Detection of dead stores and unused variables."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-liveness",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"loop-hoisting",children:"Loop Hoisting"}),"\n",(0,r.jsx)(i.p,{children:"Detect opportunities to hoist function calls that are invariant outside of loop bodies for efficiency."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-loop-hoisting",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"parameter-not-null-checked",children:"Parameter Not Null Checked"}),"\n",(0,r.jsx)(i.p,{children:"An Objective-C-specific analysis to detect when a block parameter is used before being checked for null first."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-parameter-not-null-checked",children:"Visit here for more information."})}),"\n",(0,r.jsxs)(i.h2,{id:"printf-argument-types",children:[(0,r.jsx)(i.code,{children:"printf()"})," Argument Types"]}),"\n",(0,r.jsxs)(i.p,{children:["Detect mismatches between the Java ",(0,r.jsx)(i.code,{children:"printf"})," format strings and the argument types For example, this checker will warn about the type error in ",(0,r.jsx)(i.code,{children:'printf("Hello %d", "world")'})]}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Unmaintained."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-printf-args",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"pulse",children:"Pulse"}),"\n",(0,r.jsx)(i.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-pulse",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"purity",children:"Purity"}),"\n",(0,r.jsx)(i.p,{children:'Detects pure (side-effect-free) functions. A different implementation of "impurity".'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-purity",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"quandary",children:"Quandary"}),"\n",(0,r.jsx)(i.p,{children:'The Quandary taint analysis detects flows of values between sources and sinks, except if the value went through a "sanitizer". In addition to some defaults, users can specify their own sources, sinks, and sanitizers functions.'}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Taint analysis is now supported by the Pulse checker and Quandary will be removed in the next release."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-quandary",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"racerd",children:"RacerD"}),"\n",(0,r.jsx)(i.p,{children:"Thread safety analysis."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-racerd",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"resource-leak-lab-exercise",children:"Resource Leak Lab Exercise"}),"\n",(0,r.jsx)(i.p,{children:'Toy checker for the "resource leak" write-your-own-checker exercise.'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-resource-leak-lab",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"scope-leakage",children:"Scope Leakage"}),"\n",(0,r.jsx)(i.p,{children:'The Java/Kotlin checker takes into account a set of "scope" annotations and a must-not-hold relation over the scopes. The checker raises an alarm if there exists a field access path from object A to object B, with respective scopes SA and SB, such that must-not-hold(SA, SB).'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-scope-leakage",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"static-initialization-order-fiasco",children:"Static Initialization Order Fiasco"}),"\n",(0,r.jsx)(i.p,{children:"Catches Static Initialization Order Fiascos in C++, that can lead to subtle, compiler-version-dependent errors."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-siof",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"sil-validation",children:"SIL validation"}),"\n",(0,r.jsx)(i.p,{children:"This checker validates that all SIL instructions in all procedure bodies conform to a (front-end specific) subset of SIL."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-sil-validation",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"lineage",children:"Lineage"}),"\n",(0,r.jsx)(i.p,{children:"Computes a dataflow graph"}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-lineage",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"self-in-block",children:"Self in Block"}),"\n",(0,r.jsxs)(i.p,{children:["An Objective-C-specific analysis to detect when a block captures ",(0,r.jsx)(i.code,{children:"self"}),"."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-self-in-block",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"starvation",children:"Starvation"}),"\n",(0,r.jsx)(i.p,{children:"Detect various kinds of situations when no progress is being made because of concurrency errors."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-starvation",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"topl",children:"Topl"}),"\n",(0,r.jsx)(i.p,{children:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-topl",children:"Visit here for more information."})})]})}function h(e={}){const{wrapper:i}={...(0,s.M)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},2172:(e,i,n)=>{n.d(i,{I:()=>a,M:()=>o});var r=n(1504);const s={},t=r.createContext(s);function o(e){const i=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),r.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ca86781b.abeae509.js b/assets/js/ca86781b.abeae509.js deleted file mode 100644 index e43c46664cc..00000000000 --- a/assets/js/ca86781b.abeae509.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4856],{3916:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=n(7624),s=n(2172);const t={title:"List of all checkers",hide_table_of_contents:!0},o=void 0,a={id:"all-checkers",title:"List of all checkers",description:"Here is an overview of the checkers currently available in Infer.",source:"@site/docs/all-checkers.md",sourceDirName:".",slug:"/all-checkers",permalink:"/docs/next/all-checkers",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"List of all checkers",hide_table_of_contents:!0},sidebar:"docs",previous:{title:"infer run",permalink:"/docs/next/man-infer-run"},next:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"}},c={},l=[{value:"Annotation Reachability",id:"annotation-reachability",level:2},{value:"Biabduction",id:"biabduction",level:2},{value:"Buffer Overrun Analysis (InferBO)",id:"buffer-overrun-analysis-inferbo",level:2},{value:"Config Impact Analysis",id:"config-impact-analysis",level:2},{value:"Cost: Complexity Analysis",id:"cost-complexity-analysis",level:2},{value:"Datalog-based points-to analysis",id:"datalog-based-points-to-analysis",level:2},{value:"Fragment Retains View",id:"fragment-retains-view",level:2},{value:"Impurity",id:"impurity",level:2},{value:"Inefficient keySet Iterator",id:"inefficient-keyset-iterator",level:2},{value:"Litho "Required Props"",id:"litho-required-props",level:2},{value:"Liveness",id:"liveness",level:2},{value:"Loop Hoisting",id:"loop-hoisting",level:2},{value:"Parameter Not Null Checked",id:"parameter-not-null-checked",level:2},{value:"printf() Argument Types",id:"printf-argument-types",level:2},{value:"Pulse",id:"pulse",level:2},{value:"Purity",id:"purity",level:2},{value:"Quandary",id:"quandary",level:2},{value:"RacerD",id:"racerd",level:2},{value:"Resource Leak Lab Exercise",id:"resource-leak-lab-exercise",level:2},{value:"Scope Leakage",id:"scope-leakage",level:2},{value:"Static Initialization Order Fiasco",id:"static-initialization-order-fiasco",level:2},{value:"SIL validation",id:"sil-validation",level:2},{value:"Lineage",id:"lineage",level:2},{value:"Self in Block",id:"self-in-block",level:2},{value:"Starvation",id:"starvation",level:2},{value:"Topl",id:"topl",level:2},{value:"Uninitialized Value",id:"uninitialized-value",level:2}];function d(e){const i={a:"a",code:"code",h2:"h2",p:"p",strong:"strong",...(0,s.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.p,{children:"Here is an overview of the checkers currently available in Infer."}),"\n",(0,r.jsx)(i.h2,{id:"annotation-reachability",children:"Annotation Reachability"}),"\n",(0,r.jsxs)(i.p,{children:["Given a pair of source and sink annotation, e.g. ",(0,r.jsx)(i.code,{children:"@PerformanceCritical"})," and ",(0,r.jsx)(i.code,{children:"@Expensive"}),", this checker will warn whenever some method annotated with ",(0,r.jsx)(i.code,{children:"@PerformanceCritical"})," calls, directly or indirectly, another method annotated with ",(0,r.jsx)(i.code,{children:"@Expensive"})]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-annotation-reachability",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"biabduction",children:"Biabduction"}),"\n",(0,r.jsx)(i.p,{children:"This analysis deals with a range of issues, many linked to memory safety."}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," This has been replaced by Pulse and will be removed in the next release."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-biabduction",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"buffer-overrun-analysis-inferbo",children:"Buffer Overrun Analysis (InferBO)"}),"\n",(0,r.jsx)(i.p,{children:"InferBO is a detector for out-of-bounds array accesses."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-bufferoverrun",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"config-impact-analysis",children:"Config Impact Analysis"}),"\n",(0,r.jsx)(i.p,{children:"[EXPERIMENTAL] Collects function that are called without config checks."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-config-impact-analysis",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"cost-complexity-analysis",children:"Cost: Complexity Analysis"}),"\n",(0,r.jsxs)(i.p,{children:["Computes the asymptotic complexity of functions with respect to execution cost or other user defined resources. Can be used to detect changes in the complexity with ",(0,r.jsx)(i.code,{children:"infer reportdiff"}),"."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-cost",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"datalog-based-points-to-analysis",children:"Datalog-based points-to analysis"}),"\n",(0,r.jsx)(i.p,{children:"Experimental datalog-based points-to analysis."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-datalog",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"fragment-retains-view",children:"Fragment Retains View"}),"\n",(0,r.jsx)(i.p,{children:"Detects when Android fragments are not explicitly nullified before becoming unreachable."}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Unmaintained due to poor precision."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-fragment-retains-view",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"impurity",children:"Impurity"}),"\n",(0,r.jsx)(i.p,{children:'Detects functions with potential side-effects. Same as "purity", but implemented on top of Pulse.'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-impurity",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"inefficient-keyset-iterator",children:"Inefficient keySet Iterator"}),"\n",(0,r.jsx)(i.p,{children:"Check for inefficient uses of iterators that iterate on keys then lookup their values, instead of iterating on key-value pairs directly."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"litho-required-props",children:'Litho "Required Props"'}),"\n",(0,r.jsxs)(i.p,{children:["Checks that all non-optional ",(0,r.jsx)(i.code,{children:"@Prop"}),"s have been specified when constructing Litho components."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-litho-required-props",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"liveness",children:"Liveness"}),"\n",(0,r.jsx)(i.p,{children:"Detection of dead stores and unused variables."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-liveness",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"loop-hoisting",children:"Loop Hoisting"}),"\n",(0,r.jsx)(i.p,{children:"Detect opportunities to hoist function calls that are invariant outside of loop bodies for efficiency."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-loop-hoisting",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"parameter-not-null-checked",children:"Parameter Not Null Checked"}),"\n",(0,r.jsx)(i.p,{children:"An Objective-C-specific analysis to detect when a block parameter is used before being checked for null first."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-parameter-not-null-checked",children:"Visit here for more information."})}),"\n",(0,r.jsxs)(i.h2,{id:"printf-argument-types",children:[(0,r.jsx)(i.code,{children:"printf()"})," Argument Types"]}),"\n",(0,r.jsxs)(i.p,{children:["Detect mismatches between the Java ",(0,r.jsx)(i.code,{children:"printf"})," format strings and the argument types For example, this checker will warn about the type error in ",(0,r.jsx)(i.code,{children:'printf("Hello %d", "world")'})]}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Unmaintained."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-printf-args",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"pulse",children:"Pulse"}),"\n",(0,r.jsx)(i.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-pulse",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"purity",children:"Purity"}),"\n",(0,r.jsx)(i.p,{children:'Detects pure (side-effect-free) functions. A different implementation of "impurity".'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-purity",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"quandary",children:"Quandary"}),"\n",(0,r.jsx)(i.p,{children:'The Quandary taint analysis detects flows of values between sources and sinks, except if the value went through a "sanitizer". In addition to some defaults, users can specify their own sources, sinks, and sanitizers functions.'}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Taint analysis is now supported by the Pulse checker and Quandary will be removed in the next release."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-quandary",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"racerd",children:"RacerD"}),"\n",(0,r.jsx)(i.p,{children:"Thread safety analysis."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-racerd",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"resource-leak-lab-exercise",children:"Resource Leak Lab Exercise"}),"\n",(0,r.jsx)(i.p,{children:'Toy checker for the "resource leak" write-your-own-checker exercise.'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-resource-leak-lab",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"scope-leakage",children:"Scope Leakage"}),"\n",(0,r.jsx)(i.p,{children:'The Java/Kotlin checker takes into account a set of "scope" annotations and a must-not-hold relation over the scopes. The checker raises an alarm if there exists a field access path from object A to object B, with respective scopes SA and SB, such that must-not-hold(SA, SB).'}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-scope-leakage",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"static-initialization-order-fiasco",children:"Static Initialization Order Fiasco"}),"\n",(0,r.jsx)(i.p,{children:"Catches Static Initialization Order Fiascos in C++, that can lead to subtle, compiler-version-dependent errors."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-siof",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"sil-validation",children:"SIL validation"}),"\n",(0,r.jsx)(i.p,{children:"This checker validates that all SIL instructions in all procedure bodies conform to a (front-end specific) subset of SIL."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-sil-validation",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"lineage",children:"Lineage"}),"\n",(0,r.jsx)(i.p,{children:"Computes a dataflow graph"}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-lineage",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"self-in-block",children:"Self in Block"}),"\n",(0,r.jsxs)(i.p,{children:["An Objective-C-specific analysis to detect when a block captures ",(0,r.jsx)(i.code,{children:"self"}),"."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-self-in-block",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"starvation",children:"Starvation"}),"\n",(0,r.jsx)(i.p,{children:"Detect various kinds of situations when no progress is being made because of concurrency errors."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-starvation",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"topl",children:"Topl"}),"\n",(0,r.jsx)(i.p,{children:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-topl",children:"Visit here for more information."})}),"\n",(0,r.jsx)(i.h2,{id:"uninitialized-value",children:"Uninitialized Value"}),"\n",(0,r.jsx)(i.p,{children:"Warns when values are used before having been initialized."}),"\n",(0,r.jsxs)(i.p,{children:[(0,r.jsx)(i.strong,{children:"***DEPRECATED***"})," Uninitialized value checking has moved to Pulse."]}),"\n",(0,r.jsx)(i.p,{children:(0,r.jsx)(i.a,{href:"/docs/next/checker-uninit",children:"Visit here for more information."})})]})}function h(e={}){const{wrapper:i}={...(0,s.M)(),...e.components};return i?(0,r.jsx)(i,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},2172:(e,i,n)=>{n.d(i,{I:()=>a,M:()=>o});var r=n(1504);const s={},t=r.createContext(s);function o(e){const i=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function a(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),r.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e9325e77.166166de.js b/assets/js/e9325e77.166166de.js deleted file mode 100644 index 18f491aba1e..00000000000 --- a/assets/js/e9325e77.166166de.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9656],{5860:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var n=i(7624),s=i(2172);const r={title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."},o="Topl",a={id:"checker-topl",title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects.",source:"@site/docs/checker-topl.md",sourceDirName:".",slug:"/checker-topl",permalink:"/docs/next/checker-topl",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."},sidebar:"docs",previous:{title:"Starvation",permalink:"/docs/next/checker-starvation"},next:{title:"Uninitialized Value",permalink:"/docs/next/checker-uninit"}},l={},c=[{value:"What is it?",id:"what-is-it",level:2},{value:"Specifying Properties",id:"specifying-properties",level:2},{value:"Limitations",id:"limitations",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."}),"\n",(0,n.jsxs)(t.p,{children:["Activate with ",(0,n.jsx)(t.code,{children:"--topl"}),"."]}),"\n",(0,n.jsx)(t.p,{children:"Supported languages:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"C/C++/ObjC: Experimental"}),"\n",(0,n.jsx)(t.li,{children:"C#/.Net: No"}),"\n",(0,n.jsx)(t.li,{children:"Erlang: Experimental"}),"\n",(0,n.jsx)(t.li,{children:"Hack: No"}),"\n",(0,n.jsx)(t.li,{children:"Java: Experimental"}),"\n",(0,n.jsx)(t.li,{children:"Python: No"}),"\n"]}),"\n",(0,n.jsx)(t.h1,{id:"topl",children:"Topl"}),"\n",(0,n.jsx)(t.h2,{id:"what-is-it",children:"What is it?"}),"\n",(0,n.jsxs)(t.p,{children:["Topl is an analysis framework, built on top of Infer, for statically finding violations of temporal properties. Many analyses can be encoded as temporal properties supported by Topl, such as taint analysis. As a simple example, suppose that we don't want a value returned by method ",(0,n.jsx)(t.code,{children:"source()"})," to be sent as an argument to a method ",(0,n.jsx)(t.code,{children:"sink()"}),". This can be specified as follows:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'property Taint\n prefix "Main"\n start -> start: *\n start -> tracking: source(Ret) => x := Ret\n tracking -> error: sink(Arg, VoidRet) when x == Arg\n'})}),"\n",(0,n.jsxs)(t.p,{children:["This specifies an automaton called ",(0,n.jsx)(t.code,{children:"Taint"})," that has three states (",(0,n.jsx)(t.code,{children:"start"}),", ",(0,n.jsx)(t.code,{children:"tracking"}),", ",(0,n.jsx)(t.code,{children:"error"}),"). Two of those states (",(0,n.jsx)(t.code,{children:"start"})," and ",(0,n.jsx)(t.code,{children:"error"}),") have special meaning; other states (",(0,n.jsx)(t.code,{children:"tracking"}),") can have any names. The first transition (",(0,n.jsx)(t.code,{children:"start \u2192 tracking"}),") is taken when a method called ",(0,n.jsx)(t.code,{children:"source()"})," is called, and its return value is stored in a register called ",(0,n.jsx)(t.code,{children:"x"}),"; the second transition (",(0,n.jsx)(t.code,{children:"tracking \u2192 error"}),") is taken when a method called ",(0,n.jsx)(t.code,{children:"sink()"})," is called, but only if its argument equals what was previously saved in register ",(0,n.jsx)(t.code,{children:"x"}),".\nThis property is violated in the following Java code:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'public class Main {\n static void f() { g(tito(source())); }\n static void g(Object x) { h(x); }\n static void h(Object x) { sink(x); }\n static Object tito(Object x) { return x; }\n static Object source() { return "dirty"; }\n static void sink(Object x) {}\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["Note that ",(0,n.jsx)(t.code,{children:"source()"})," and ",(0,n.jsx)(t.code,{children:"sink()"})," are not called from the same method, and that the \u201cdirty\u201d object is passed around a few times before finally reaching the sink. Assuming that the property is in a file ",(0,n.jsx)(t.code,{children:"taint.topl"})," and the Java code in a file ",(0,n.jsx)(t.code,{children:"Main.java"}),", you can invoke Infer with the following command:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"infer --topl --topl-properties taint.topl -- javac Main.java\n"})}),"\n",(0,n.jsx)(t.p,{children:"It will display the following error:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"Main.java:2: error: Topl Error\n property Taint reaches state error.\n 1. public class Main {\n 2. > static void f() { g(tito(source())); }\n 3. static void g(Object x) { h(x); }\n 4. static void h(Object x) { sink(x); }\n"})}),"\n",(0,n.jsx)(t.p,{children:"To get a full trace, use the command"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:"infer explore\n"})}),"\n",(0,n.jsx)(t.h2,{id:"specifying-properties",children:"Specifying Properties"}),"\n",(0,n.jsx)(t.p,{children:"A property is a nondeterministic automaton that can remember values in registers. An execution that drives the automaton from the start state to the error state will make Infer report an issue, and the trace that it produces will indicate which parts of the program drive which transitions of the automaton."}),"\n",(0,n.jsx)(t.p,{children:"The general form of a property is the following:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'property Name\n message "Optional error message" // This line can be missing\n prefix "Prefix" // There can be zero, one, or more prefix declarations\n sourceState -> targetState: Pattern(Arg1,...,ArgN,Ret) when Condition => Action\n'})}),"\n",(0,n.jsx)(t.p,{children:"The property name and the optional error message are used for reporting issues. The prefix declarations are used to simplify Patterns. The core of the property is the list of transitions."}),"\n",(0,n.jsx)(t.p,{children:"Each transition has a source state and a target state. The special transition label * means that the transition is always taken. Typically, there is a transition"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:" start -> start: *\n"})}),"\n",(0,n.jsx)(t.p,{children:"meaning that the property can start anywhere, not just at the beginning of a method."}),"\n",(0,n.jsx)(t.p,{children:"Otherwise, the label on a transition contains:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["a ",(0,n.jsx)(t.em,{children:"Pattern"}),", which indicates what kind of instruction in the program drives this transition;"]}),"\n",(0,n.jsx)(t.li,{children:"a list of transition variable bindings (above named Arg1, ..., but any identifier starting with uppercase letters works);"}),"\n",(0,n.jsx)(t.li,{children:"possibly a boolean Condition, which can refer to transition variables, registers and fields;"}),"\n",(0,n.jsxs)(t.li,{children:["possibly and Action, which is a list sequence of assignments of the form ",(0,n.jsx)(t.em,{children:"register"})," := ",(0,n.jsx)(t.em,{children:"TransitionVariable"})," (registers do not need to be declared, and any identifier starting with a lowercase letter works)."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"There are two types of patterns:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["a regex that matches method names","\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"if the regex uses non-letters (such as dots) it must be within double-quotes; otherwise, double quotes are optional"}),"\n",(0,n.jsx)(t.li,{children:"the prefix declarations are used to add potential prefixes to the regex. The combine regex is essentially \u201c(prefix_regex_a | prefix_regex_b) transition_pattern_regex\u201c"}),"\n",(0,n.jsxs)(t.li,{children:["for a method with n arguments, there must be n+1 transition variables to get a match. The first n transition variables get bound to the argument values, and the last transition variable gets bound to the return value. ",(0,n.jsx)(t.em,{children:"This is true even for the case in which the return type is void"}),"."]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["the special keyword ",(0,n.jsx)(t.strong,{children:"#ArrayWrite"}),". In that case, there should be two transition variables like \u201c(Array, Index)\u201d \u2014 Array gets bound to the array object, and Index gets bound to the index at which the write happens."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"The condition supports the following kinds of expressions:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Referring to identifiers: transition variables and registers"}),"\n",(0,n.jsxs)(t.li,{children:["Field access over objects in the form ",(0,n.jsx)(t.code,{children:"Identifier:Type.FieldName"}),", e.g. ",(0,n.jsx)(t.code,{children:"X:MyClass.myField"})," (this is currently only supported for Erlang)"]}),"\n",(0,n.jsx)(t.li,{children:"Integer literals"}),"\n",(0,n.jsxs)(t.li,{children:["The usual comparison operators (",(0,n.jsx)(t.code,{children:"=="}),", ",(0,n.jsx)(t.code,{children:"!="}),", ",(0,n.jsx)(t.code,{children:"<"}),", ",(0,n.jsx)(t.code,{children:">"}),", ",(0,n.jsx)(t.code,{children:">="}),", ",(0,n.jsx)(t.code,{children:"<="}),") and conjunctions (",(0,n.jsx)(t.code,{children:"&&"}),")"]}),"\n",(0,n.jsxs)(t.li,{children:["Reachability predicates of the form ",(0,n.jsx)(t.code,{children:"Ident1 ~~> Ident2"})," meaning that ",(0,n.jsx)(t.code,{children:"Ident2"})," can be reached via pointers/fields from ",(0,n.jsx)(t.code,{children:"Ident1"})," in the heap"]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["For several examples, see ",(0,n.jsx)(t.a,{href:"https://github.com/facebook/infer/tree/main/infer/tests/codetoanalyze/java/topl",children:"https://github.com/facebook/infer/tree/main/infer/tests/codetoanalyze/java/topl"})]}),"\n",(0,n.jsx)(t.h2,{id:"limitations",children:"Limitations"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"By design, some problems may be missed. Topl is built on Pulse, which attempts to minimize false positives, at the cost of sometimes having false negatives."}),"\n",(0,n.jsxs)(t.li,{children:["Analysis time increases exponentially with the number of registers used in properties.","\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"In theory, there should be no significant slowdown if registers belong to different properties, but the implementation is not yet optimized."}),"\n",(0,n.jsx)(t.li,{children:"If there are many registers within the same property, then the slowdown is unavoidable (without some significant breakthrough). However, the maximum number of registers we ever used for one practical property was 3."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,n.jsx)(t.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/next/all-issue-types#topl_error",children:"TOPL_ERROR"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"/docs/next/all-issue-types#topl_error_latent",children:"TOPL_ERROR_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.M)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},2172:(e,t,i)=>{i.d(t,{I:()=>a,M:()=>o});var n=i(1504);const s={},r=n.createContext(s);function o(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e9325e77.b0fe78fe.js b/assets/js/e9325e77.b0fe78fe.js new file mode 100644 index 00000000000..3ea991e879d --- /dev/null +++ b/assets/js/e9325e77.b0fe78fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9656],{5860:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var i=n(7624),s=n(2172);const r={title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."},o="Topl",a={id:"checker-topl",title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects.",source:"@site/docs/checker-topl.md",sourceDirName:".",slug:"/checker-topl",permalink:"/docs/next/checker-topl",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Topl",description:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."},sidebar:"docs",previous:{title:"Starvation",permalink:"/docs/next/checker-starvation"},next:{title:"About Infer",permalink:"/docs/next/about-Infer"}},l={},c=[{value:"What is it?",id:"what-is-it",level:2},{value:"Specifying Properties",id:"specifying-properties",level:2},{value:"Limitations",id:"limitations",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function d(e){const t={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"Detect errors based on user-provided state machines describing temporal properties over multiple objects."}),"\n",(0,i.jsxs)(t.p,{children:["Activate with ",(0,i.jsx)(t.code,{children:"--topl"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Supported languages:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"C/C++/ObjC: Experimental"}),"\n",(0,i.jsx)(t.li,{children:"C#/.Net: No"}),"\n",(0,i.jsx)(t.li,{children:"Erlang: Experimental"}),"\n",(0,i.jsx)(t.li,{children:"Hack: No"}),"\n",(0,i.jsx)(t.li,{children:"Java: Experimental"}),"\n",(0,i.jsx)(t.li,{children:"Python: No"}),"\n"]}),"\n",(0,i.jsx)(t.h1,{id:"topl",children:"Topl"}),"\n",(0,i.jsx)(t.h2,{id:"what-is-it",children:"What is it?"}),"\n",(0,i.jsxs)(t.p,{children:["Topl is an analysis framework, built on top of Infer, for statically finding violations of temporal properties. Many analyses can be encoded as temporal properties supported by Topl, such as taint analysis. As a simple example, suppose that we don't want a value returned by method ",(0,i.jsx)(t.code,{children:"source()"})," to be sent as an argument to a method ",(0,i.jsx)(t.code,{children:"sink()"}),". This can be specified as follows:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'property Taint\n prefix "Main"\n start -> start: *\n start -> tracking: source(Ret) => x := Ret\n tracking -> error: sink(Arg, VoidRet) when x == Arg\n'})}),"\n",(0,i.jsxs)(t.p,{children:["This specifies an automaton called ",(0,i.jsx)(t.code,{children:"Taint"})," that has three states (",(0,i.jsx)(t.code,{children:"start"}),", ",(0,i.jsx)(t.code,{children:"tracking"}),", ",(0,i.jsx)(t.code,{children:"error"}),"). Two of those states (",(0,i.jsx)(t.code,{children:"start"})," and ",(0,i.jsx)(t.code,{children:"error"}),") have special meaning; other states (",(0,i.jsx)(t.code,{children:"tracking"}),") can have any names. The first transition (",(0,i.jsx)(t.code,{children:"start \u2192 tracking"}),") is taken when a method called ",(0,i.jsx)(t.code,{children:"source()"})," is called, and its return value is stored in a register called ",(0,i.jsx)(t.code,{children:"x"}),"; the second transition (",(0,i.jsx)(t.code,{children:"tracking \u2192 error"}),") is taken when a method called ",(0,i.jsx)(t.code,{children:"sink()"})," is called, but only if its argument equals what was previously saved in register ",(0,i.jsx)(t.code,{children:"x"}),".\nThis property is violated in the following Java code:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'public class Main {\n static void f() { g(tito(source())); }\n static void g(Object x) { h(x); }\n static void h(Object x) { sink(x); }\n static Object tito(Object x) { return x; }\n static Object source() { return "dirty"; }\n static void sink(Object x) {}\n}\n'})}),"\n",(0,i.jsxs)(t.p,{children:["Note that ",(0,i.jsx)(t.code,{children:"source()"})," and ",(0,i.jsx)(t.code,{children:"sink()"})," are not called from the same method, and that the \u201cdirty\u201d object is passed around a few times before finally reaching the sink. Assuming that the property is in a file ",(0,i.jsx)(t.code,{children:"taint.topl"})," and the Java code in a file ",(0,i.jsx)(t.code,{children:"Main.java"}),", you can invoke Infer with the following command:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"infer --topl --topl-properties taint.topl -- javac Main.java\n"})}),"\n",(0,i.jsx)(t.p,{children:"It will display the following error:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"Main.java:2: error: Topl Error\n property Taint reaches state error.\n 1. public class Main {\n 2. > static void f() { g(tito(source())); }\n 3. static void g(Object x) { h(x); }\n 4. static void h(Object x) { sink(x); }\n"})}),"\n",(0,i.jsx)(t.p,{children:"To get a full trace, use the command"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"infer explore\n"})}),"\n",(0,i.jsx)(t.h2,{id:"specifying-properties",children:"Specifying Properties"}),"\n",(0,i.jsx)(t.p,{children:"A property is a nondeterministic automaton that can remember values in registers. An execution that drives the automaton from the start state to the error state will make Infer report an issue, and the trace that it produces will indicate which parts of the program drive which transitions of the automaton."}),"\n",(0,i.jsx)(t.p,{children:"The general form of a property is the following:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'property Name\n message "Optional error message" // This line can be missing\n prefix "Prefix" // There can be zero, one, or more prefix declarations\n sourceState -> targetState: Pattern(Arg1,...,ArgN,Ret) when Condition => Action\n'})}),"\n",(0,i.jsx)(t.p,{children:"The property name and the optional error message are used for reporting issues. The prefix declarations are used to simplify Patterns. The core of the property is the list of transitions."}),"\n",(0,i.jsx)(t.p,{children:"Each transition has a source state and a target state. The special transition label * means that the transition is always taken. Typically, there is a transition"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:" start -> start: *\n"})}),"\n",(0,i.jsx)(t.p,{children:"meaning that the property can start anywhere, not just at the beginning of a method."}),"\n",(0,i.jsx)(t.p,{children:"Otherwise, the label on a transition contains:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["a ",(0,i.jsx)(t.em,{children:"Pattern"}),", which indicates what kind of instruction in the program drives this transition;"]}),"\n",(0,i.jsx)(t.li,{children:"a list of transition variable bindings (above named Arg1, ..., but any identifier starting with uppercase letters works);"}),"\n",(0,i.jsx)(t.li,{children:"possibly a boolean Condition, which can refer to transition variables, registers and fields;"}),"\n",(0,i.jsxs)(t.li,{children:["possibly and Action, which is a list sequence of assignments of the form ",(0,i.jsx)(t.em,{children:"register"})," := ",(0,i.jsx)(t.em,{children:"TransitionVariable"})," (registers do not need to be declared, and any identifier starting with a lowercase letter works)."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"There are two types of patterns:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["a regex that matches method names","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"if the regex uses non-letters (such as dots) it must be within double-quotes; otherwise, double quotes are optional"}),"\n",(0,i.jsx)(t.li,{children:"the prefix declarations are used to add potential prefixes to the regex. The combine regex is essentially \u201c(prefix_regex_a | prefix_regex_b) transition_pattern_regex\u201c"}),"\n",(0,i.jsxs)(t.li,{children:["for a method with n arguments, there must be n+1 transition variables to get a match. The first n transition variables get bound to the argument values, and the last transition variable gets bound to the return value. ",(0,i.jsx)(t.em,{children:"This is true even for the case in which the return type is void"}),"."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(t.li,{children:["the special keyword ",(0,i.jsx)(t.strong,{children:"#ArrayWrite"}),". In that case, there should be two transition variables like \u201c(Array, Index)\u201d \u2014 Array gets bound to the array object, and Index gets bound to the index at which the write happens."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"The condition supports the following kinds of expressions:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Referring to identifiers: transition variables and registers"}),"\n",(0,i.jsxs)(t.li,{children:["Field access over objects in the form ",(0,i.jsx)(t.code,{children:"Identifier:Type.FieldName"}),", e.g. ",(0,i.jsx)(t.code,{children:"X:MyClass.myField"})," (this is currently only supported for Erlang)"]}),"\n",(0,i.jsx)(t.li,{children:"Integer literals"}),"\n",(0,i.jsxs)(t.li,{children:["The usual comparison operators (",(0,i.jsx)(t.code,{children:"=="}),", ",(0,i.jsx)(t.code,{children:"!="}),", ",(0,i.jsx)(t.code,{children:"<"}),", ",(0,i.jsx)(t.code,{children:">"}),", ",(0,i.jsx)(t.code,{children:">="}),", ",(0,i.jsx)(t.code,{children:"<="}),") and conjunctions (",(0,i.jsx)(t.code,{children:"&&"}),")"]}),"\n",(0,i.jsxs)(t.li,{children:["Reachability predicates of the form ",(0,i.jsx)(t.code,{children:"Ident1 ~~> Ident2"})," meaning that ",(0,i.jsx)(t.code,{children:"Ident2"})," can be reached via pointers/fields from ",(0,i.jsx)(t.code,{children:"Ident1"})," in the heap"]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["For several examples, see ",(0,i.jsx)(t.a,{href:"https://github.com/facebook/infer/tree/main/infer/tests/codetoanalyze/java/topl",children:"https://github.com/facebook/infer/tree/main/infer/tests/codetoanalyze/java/topl"})]}),"\n",(0,i.jsx)(t.h2,{id:"limitations",children:"Limitations"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"By design, some problems may be missed. Topl is built on Pulse, which attempts to minimize false positives, at the cost of sometimes having false negatives."}),"\n",(0,i.jsxs)(t.li,{children:["Analysis time increases exponentially with the number of registers used in properties.","\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"In theory, there should be no significant slowdown if registers belong to different properties, but the implementation is not yet optimized."}),"\n",(0,i.jsx)(t.li,{children:"If there are many registers within the same property, then the slowdown is unavoidable (without some significant breakthrough). However, the maximum number of registers we ever used for one practical property was 3."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,i.jsx)(t.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/docs/next/all-issue-types#topl_error",children:"TOPL_ERROR"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/docs/next/all-issue-types#topl_error_latent",children:"TOPL_ERROR_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.M)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},2172:(e,t,n)=>{n.d(t,{I:()=>a,M:()=>o});var i=n(1504);const s={},r=i.createContext(s);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.53cbafeb.js b/assets/js/main.53cbafeb.js deleted file mode 100644 index 1ce6bb177b7..00000000000 --- a/assets/js/main.53cbafeb.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.53cbafeb.js.LICENSE.txt */ -(self.webpackChunk=self.webpackChunk||[]).push([[1590],{5052:(e,t,n)=>{"use strict";n.d(t,{I:()=>o});var r=n(1504);function o(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},628:(e,t,n)=>{"use strict";n.d(t,{c:()=>p});n(1504);var r=n(8852),o=n.n(r),a=n(4504);const i={"00d3276d":[()=>n.e(2068).then(n.bind(n,9436)),"@site/blog/2016-06-23-first-opensourceversary.md",9436],"0346afaa":[()=>n.e(1352).then(n.bind(n,6264)),"@site/versioned_docs/version-1.1.0/man-infer-debug.md",6264],"041e4035":[()=>n.e(1624).then(n.bind(n,1292)),"@site/docs/checker-starvation.md",1292],"04f8d6af":[()=>n.e(9728).then(n.bind(n,3796)),"@site/versioned_docs/version-1.1.0/checker-liveness.md",3796],"06d8773d":[()=>n.e(8384).then(n.bind(n,3380)),"@site/docs/checker-litho-required-props.md",3380],"07d14bbd":[()=>n.e(7848).then(n.bind(n,4604)),"@site/docs/checker-uninit.md",4604],"0ac93784":[()=>n.e(7296).then(n.bind(n,308)),"@site/versioned_docs/version-1.0.0/checker-annotation-reachability.md",308],"0c0efcaa":[()=>n.e(8528).then(n.bind(n,3924)),"@site/versioned_docs/version-1.1.0/checker-litho-required-props.md",3924],"0fe8a02a":[()=>n.e(6452).then(n.bind(n,9684)),"@site/docs/versions.md",9684],"12577cfd":[()=>n.e(3128).then(n.bind(n,1624)),"@site/versioned_docs/version-1.0.0/all-issue-types.md",1624],"128c6d36":[()=>n.e(7840).then(n.bind(n,4964)),"@site/docs/checker-printf-args.md",4964],"1460e89b":[()=>n.e(1008).then(n.bind(n,5728)),"@site/versioned_docs/version-1.0.0/02-separation-logic-and-biabduction.md",5728],"15a3954c":[()=>n.e(6322).then(n.bind(n,1708)),"@site/versioned_docs/version-1.0.0/checker-racerd.md",1708],"16fe8a4c":[()=>n.e(920).then(n.bind(n,7820)),"@site/docs/00-getting-started.md",7820],17896441:[()=>Promise.all([n.e(2176),n.e(9116),n.e(6752)]).then(n.bind(n,5104)),"@theme/DocItem",5104],"18328e9e":[()=>n.e(7952).then(n.bind(n,7480)),"@site/docs/checker-purity.md",7480],"184ad633":[()=>n.e(208).then(n.bind(n,7168)),"@site/versioned_docs/version-1.1.0/checker-dotnet-resource-leak.md",7168],"1906a68b":[()=>n.e(8928).then(n.bind(n,2428)),"@site/docs/02-separation-logic-and-biabduction.md",2428],"1a4e3797":[()=>Promise.all([n.e(2176),n.e(9648)]).then(n.bind(n,3416)),"@theme/SearchPage",3416],"1c7a9c9f":[()=>n.e(9792).then(n.bind(n,9804)),"@site/docs/checker-annotation-reachability.md",9804],"1d8647da":[()=>n.e(5336).then(n.bind(n,192)),"@site/versioned_docs/version-1.1.0/checker-quandary.md",192],"1db0afb7":[()=>n.e(3876).then(n.bind(n,5500)),"@site/versioned_docs/version-1.0.0/man-infer-reportdiff.md",5500],"1dbe42a7":[()=>n.e(3796).then(n.bind(n,400)),"@site/docs/01-man-pages.md",400],"1df9637e":[()=>n.e(7948).then(n.bind(n,9708)),"@site/docs/checker-cost.md",9708],"1fdfdeaa":[()=>n.e(1085).then(n.bind(n,9652)),"@site/docs/checker-biabduction.md",9652],21614072:[()=>n.e(172).then(n.bind(n,6976)),"@site/docs/man-infer-run.md",6976],"219c4568":[()=>n.e(1088).then(n.bind(n,7e3)),"@site/versioned_docs/version-1.0.0/man-infer-explore.md",7e3],"21a9d6ed":[()=>n.e(1672).then(n.bind(n,5776)),"@site/docs/man-infer-help.md",5776],"25a5a20c":[()=>n.e(6180).then(n.bind(n,3620)),"@site/docs/checker-bufferoverrun.md",3620],"293e08e8":[()=>n.e(9700).then(n.bind(n,4952)),"@site/blog/2017-10-20-ocamlformat-released.md?truncated=true",4952],"2ba1d2b8":[()=>n.e(7724).then(n.bind(n,832)),"@site/versioned_docs/version-1.0.0/versions.md",832],"31868bec":[()=>n.e(6868).then(n.t.bind(n,2080,19)),"/home/runner/work/infer/infer/website/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",2080],33776668:[()=>n.e(8906).then(n.bind(n,3192)),"@site/versioned_docs/version-1.1.0/checker-config-checks-between-markers.md",3192],"3423820d":[()=>n.e(2756).then(n.bind(n,1916)),"@site/blog/2017-10-20-ocamlformat-released.md",1916],"34fbd09a":[()=>n.e(9456).then(n.bind(n,3811)),"@site/versioned_docs/version-1.1.0/checker-biabduction.md",3811],"3c055f5e":[()=>n.e(7920).then(n.bind(n,596)),"@site/docs/man-infer-capture.md",596],"3c653e3b":[()=>n.e(904).then(n.bind(n,5845)),"@site/versioned_docs/version-1.1.0/01-man-pages.md",5845],"3c741b47":[()=>n.e(644).then(n.bind(n,868)),"@site/versioned_docs/version-1.1.0/man-infer.md",868],"3caf9b73":[()=>n.e(3043).then(n.bind(n,5660)),"@site/versioned_docs/version-1.0.0/checker-liveness.md",5660],"3d9729af":[()=>n.e(7192).then(n.bind(n,3676)),"@site/versioned_docs/version-1.1.0/checker-topl.md",3676],"3eac2097":[()=>n.e(5244).then(n.bind(n,2088)),"@site/docs/checker-liveness.md",2088],"3eb0a99f":[()=>n.e(9400).then(n.bind(n,2753)),"@site/blog/2016-08-30-curryon-rome-talk.md?truncated=true",2753],"3f2a1ecb":[()=>n.e(264).then(n.bind(n,6868)),"@site/versioned_docs/version-1.1.0/checker-starvation.md",6868],"413f2abb":[()=>n.e(2762).then(n.bind(n,8480)),"@site/versioned_docs/version-1.1.0/02-separation-logic-and-biabduction.md",8480],"420497a2":[()=>n.e(2760).then(n.bind(n,2188)),"@site/versioned_docs/version-1.1.0/checker-linters.md",2188],"43455a69":[()=>n.e(6828).then(n.bind(n,9616)),"@site/versioned_docs/version-1.0.0/04-absint-framework.md",9616],"45d37095":[()=>n.e(2200).then(n.bind(n,9880)),"@site/versioned_docs/version-1.1.0/checker-bufferoverrun.md",9880],"491a3217":[()=>n.e(8768).then(n.bind(n,8532)),"@site/blog/2016-11-28-atscale16.md?truncated=true",8532],"495e5e06":[()=>n.e(4072).then(n.bind(n,6436)),"@site/versioned_docs/version-1.0.0/checker-self-in-block.md",6436],"49bfadd9":[()=>n.e(6209).then(n.bind(n,8196)),"@site/versioned_docs/version-1.0.0/checker-purity.md",8196],"4c2546f9":[()=>n.e(4724).then(n.bind(n,9224)),"@site/docs/man-infer-explore.md",9224],"4dac5fec":[()=>n.e(6714).then(n.bind(n,3508)),"@site/docs/man-infer.md",3508],"4fefa35c":[()=>n.e(8916).then(n.bind(n,9892)),"@site/versioned_docs/version-1.0.0/checker-inefficient-keyset-iterator.md",9892],"509dc7bf":[()=>n.e(3044).then(n.bind(n,6804)),"@site/versioned_docs/version-1.1.0/checker-config-impact-analysis.md",6804],"556d04db":[()=>n.e(8008).then(n.bind(n,8804)),"@site/docs/checker-scope-leakage.md",8804],"56ebd09a":[()=>n.e(7012).then(n.bind(n,9424)),"@site/docs/00-hello-world.md",9424],"57bcddd6":[()=>n.e(6730).then(n.bind(n,6256)),"@site/versioned_docs/version-1.1.0/checker-eradicate.md",6256],"58de4400":[()=>n.e(820).then(n.bind(n,6872)),"@site/blog/2015-05-22-Infer-on-open-source-android-apps.md?truncated=true",6872],"5a5dcc21":[()=>n.e(5505).then(n.bind(n,8280)),"@site/docs/04-absint-framework.md",8280],"5bb07cf5":[()=>n.e(6576).then(n.bind(n,60)),"@site/docs/checker-lineage.md",60],"5bb3de56":[()=>n.e(8012).then(n.bind(n,6909)),"@site/versioned_docs/version-1.0.0/checker-loop-hoisting.md",6909],"5c9e12d1":[()=>n.e(1260).then(n.t.bind(n,590,19)),"/home/runner/work/infer/infer/website/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",590],"5e95c892":[()=>n.e(4304).then(n.bind(n,3564)),"@theme/DocsRoot",3564],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,7768)),"@generated/docusaurus.config",7768],"5f403532":[()=>n.e(5008).then(n.bind(n,9228)),"@site/docs/01-steps-for-ci.md",9228],"6021085e":[()=>n.e(4217).then(n.bind(n,1380)),"@site/docs/man-infer-debug.md",1380],"6297ff83":[()=>n.e(4824).then(n.bind(n,9680)),"@site/docs/man-infer-compile.md",9680],"62b182e9":[()=>n.e(9064).then(n.bind(n,9884)),"@site/versioned_docs/version-1.0.0/checker-uninit.md",9884],"62e81aa6":[()=>n.e(7664).then(n.t.bind(n,736,19)),"~docs/default/version-1-0-0-metadata-prop-608.json",736],"64cca8ef":[()=>n.e(4486).then(n.bind(n,3052)),"@site/versioned_docs/version-1.1.0/support.md",3052],"64f1f19c":[()=>n.e(1912).then(n.bind(n,820)),"@site/versioned_docs/version-1.1.0/01-analyzing-apps-or-projects.md",820],"671939c9":[()=>n.e(1792).then(n.bind(n,5476)),"@site/versioned_docs/version-1.1.0/02-about-infer.md",5476],"6baf1826":[()=>n.e(2416).then(n.bind(n,4312)),"@site/versioned_docs/version-1.0.0/man-infer-debug.md",4312],"6d752ef5":[()=>n.e(7712).then(n.bind(n,7144)),"@site/versioned_docs/version-1.1.0/checker-cost.md",7144],"70793eb2":[()=>n.e(1660).then(n.bind(n,4232)),"@site/docs/04-internal-API.md",4232],"71a2656f":[()=>n.e(5840).then(n.bind(n,3640)),"@site/versioned_docs/version-1.1.0/man-infer-analyze.md",3640],79263788:[()=>n.e(2356).then(n.bind(n,4932)),"@site/versioned_docs/version-1.1.0/04-internal-API.md",4932],"7b1f0035":[()=>n.e(6040).then(n.bind(n,4584)),"@site/docs/02-about-infer.md",4584],"7d50aa41":[()=>n.e(5708).then(n.bind(n,7612)),"@site/versioned_docs/version-1.0.0/checker-biabduction.md",7612],"7efbfa7e":[()=>n.e(1412).then(n.bind(n,4388)),"@site/docs/man-infer-reportdiff.md",4388],"7f661f82":[()=>n.e(5752).then(n.bind(n,5044)),"@site/versioned_docs/version-1.1.0/01-steps-for-ci.md",5044],"814f3328":[()=>n.e(5512).then(n.t.bind(n,4352,19)),"~blog/default/blog-post-list-prop-default.json",4352],"879f7a7c":[()=>n.e(9096).then(n.bind(n,1404)),"@site/versioned_docs/version-1.0.0/00-getting-started.md",1404],"8919ea97":[()=>n.e(8372).then(n.bind(n,216)),"@site/versioned_docs/version-1.1.0/checker-pulse.md",216],"8a061d83":[()=>n.e(5584).then(n.bind(n,4444)),"@site/versioned_docs/version-1.1.0/checker-printf-args.md",4444],"8db808e7":[()=>n.e(8444).then(n.bind(n,4496)),"@site/versioned_docs/version-1.1.0/01-infer-workflow.md",4496],"8fdeae25":[()=>n.e(6164).then(n.bind(n,7148)),"@site/docs/checker-pulse.md",7148],"9118549b":[()=>n.e(2008).then(n.bind(n,1908)),"@site/docs/checker-quandary.md",1908],92185360:[()=>n.e(6416).then(n.bind(n,6752)),"@site/versioned_docs/version-1.0.0/man-infer-capture.md",6752],"9242256d":[()=>n.e(1080).then(n.bind(n,2180)),"@site/versioned_docs/version-1.0.0/man-infer-run.md",2180],"9258f162":[()=>n.e(379).then(n.bind(n,6408)),"@site/versioned_docs/version-1.1.0/checker-uninit.md",6408],"935f2afb":[()=>n.e(5696).then(n.t.bind(n,5988,19)),"~docs/default/version-current-metadata-prop-751.json",5988],"937dc5a6":[()=>n.e(2728).then(n.bind(n,7528)),"@site/docs/checker-parameter-not-null-checked.md",7528],"9702a600":[()=>n.e(8808).then(n.bind(n,6696)),"@site/blog/2016-04-07-mobileatscale-london-talk.md?truncated=true",6696],"99b7fc87":[()=>n.e(7180).then(n.bind(n,3951)),"@site/versioned_docs/version-1.0.0/02-about-infer.md",3951],"99c7964b":[()=>n.e(3048).then(n.bind(n,7112)),"@site/docs/checker-siof.md",7112],"9a49882e":[()=>n.e(2872).then(n.bind(n,2576)),"@site/versioned_docs/version-1.0.0/checker-cost.md",2576],"9d221b96":[()=>n.e(4184).then(n.bind(n,7704)),"@site/versioned_docs/version-1.1.0/checker-self-in-block.md",7704],"9d4bdb35":[()=>n.e(2708).then(n.bind(n,480)),"@site/versioned_docs/version-1.1.0/checker-resource-leak-lab.md",480],"9e4087bc":[()=>n.e(7028).then(n.bind(n,6140)),"@theme/BlogArchivePage",6140],a02168a2:[()=>n.e(8858).then(n.bind(n,5088)),"@site/versioned_docs/version-1.1.0/man-infer-help.md",5088],a2bed8f0:[()=>n.e(8392).then(n.bind(n,140)),"@site/docs/man-infer-analyze.md",140],a33b6a74:[()=>n.e(3596).then(n.bind(n,2324)),"@site/docs/checker-fragment-retains-view.md",2324],a373fd77:[()=>n.e(4308).then(n.bind(n,6340)),"@site/docs/checker-inefficient-keyset-iterator.md",6340],a5a260f1:[()=>n.e(2096).then(n.bind(n,4944)),"@site/blog/2016-04-07-mobileatscale-london-talk.md",4944],a6aa9e1f:[()=>Promise.all([n.e(2176),n.e(9116),n.e(606),n.e(4976)]).then(n.bind(n,4236)),"@theme/BlogListPage",4236],a6f42423:[()=>n.e(7552).then(n.bind(n,9944)),"@site/versioned_docs/version-1.0.0/01-man-pages.md",9944],a78783ee:[()=>n.e(4220).then(n.bind(n,6912)),"@site/versioned_docs/version-1.0.0/01-advanced-features.md",6912],a7bd4aaa:[()=>n.e(6500).then(n.bind(n,2e3)),"@theme/DocVersionRoot",2e3],a90afd08:[()=>n.e(8532).then(n.bind(n,5608)),"@site/versioned_docs/version-1.0.0/checker-topl-pulse.md",5608],a94703ab:[()=>Promise.all([n.e(2176),n.e(4666)]).then(n.bind(n,996)),"@theme/DocRoot",996],a9946d6a:[()=>n.e(8448).then(n.bind(n,1532)),"@site/versioned_docs/version-1.0.0/00-hello-world.md",1532],aa0b35eb:[()=>n.e(8176).then(n.bind(n,6844)),"@site/blog/2016-08-30-curryon-rome-talk.md",6844],aae2c465:[()=>n.e(4152).then(n.bind(n,6516)),"@site/versioned_docs/version-1.0.0/man-infer-analyze.md",6516],aaff9110:[()=>n.e(7208).then(n.bind(n,2744)),"@site/versioned_docs/version-1.1.0/man-infer-reportdiff.md",2744],ab17452f:[()=>n.e(3840).then(n.bind(n,9484)),"@site/versioned_docs/version-1.1.0/man-infer-explore.md",9484],abc9d724:[()=>n.e(8980).then(n.bind(n,2548)),"@site/versioned_docs/version-1.1.0/man-infer-capture.md",2548],acaf655c:[()=>n.e(5680).then(n.bind(n,7732)),"@site/versioned_docs/version-1.1.0/00-getting-started.md",7732],acb2d06a:[()=>n.e(7996).then(n.bind(n,2024)),"@site/blog/2016-06-23-first-opensourceversary.md?truncated=true",2024],ae565638:[()=>n.e(3132).then(n.bind(n,644)),"@site/versioned_docs/version-1.1.0/checker-impurity.md",644],af0818da:[()=>n.e(4156).then(n.t.bind(n,6792,19)),"/home/runner/work/infer/infer/website/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",6792],af0d8a1e:[()=>n.e(2012).then(n.bind(n,64)),"@site/versioned_docs/version-1.0.0/01-infer-workflow.md",64],b065408b:[()=>n.e(8934).then(n.bind(n,4044)),"@site/versioned_docs/version-1.1.0/man-infer-report.md",4044],b2b675dd:[()=>n.e(6292).then(n.t.bind(n,6180,19)),"~blog/default/blog-c06.json",6180],b2f554cd:[()=>n.e(6880).then(n.t.bind(n,8256,19)),"~blog/default/blog-archive-80c.json",8256],b4e1da39:[()=>n.e(1272).then(n.bind(n,5920)),"@site/versioned_docs/version-1.0.0/man-infer-compile.md",5920],b5b9c8e0:[()=>n.e(8252).then(n.bind(n,2936)),"@site/versioned_docs/version-1.0.0/checker-starvation.md",2936],b784ffba:[()=>n.e(6608).then(n.bind(n,76)),"@site/versioned_docs/version-1.0.0/man-infer-help.md",76],b9f8aa82:[()=>n.e(9808).then(n.bind(n,3960)),"@site/docs/man-infer-report.md",3960],bab022f4:[()=>n.e(188).then(n.bind(n,2404)),"@site/docs/01-infer-workflow.md",2404],bbdc39ec:[()=>n.e(3116).then(n.bind(n,1132)),"@site/docs/checker-sil-validation.md",1132],bc318449:[()=>n.e(6748).then(n.bind(n,7436)),"@site/versioned_docs/version-1.0.0/01-steps-for-ci.md",7436],bc3f1a98:[()=>n.e(1200).then(n.bind(n,684)),"@site/versioned_docs/version-1.1.0/man-infer-compile.md",684],bd470307:[()=>n.e(3612).then(n.bind(n,8488)),"@site/docs/checker-self-in-block.md",8488],bd8da646:[()=>n.e(9258).then(n.bind(n,1108)),"@site/versioned_docs/version-1.0.0/checker-topl-biabd.md",1108],be77d225:[()=>n.e(2900).then(n.bind(n,5224)),"@site/versioned_docs/version-1.1.0/04-absint-framework.md",5224],bf6aacca:[()=>n.e(6732).then(n.bind(n,7948)),"@site/versioned_docs/version-1.1.0/all-issue-types.md",7948],c027c09e:[()=>n.e(2764).then(n.bind(n,3732)),"@site/versioned_docs/version-1.0.0/checker-printf-args.md",3732],c14a26e3:[()=>n.e(4616).then(n.bind(n,7868)),"@site/versioned_docs/version-1.0.0/checker-immutable-cast.md",7868],c222a988:[()=>n.e(7332).then(n.bind(n,3276)),"@site/docs/checker-resource-leak-lab.md",3276],c26add1d:[()=>n.e(5048).then(n.bind(n,6420)),"@site/versioned_docs/version-1.1.0/checker-fragment-retains-view.md",6420],c2d67624:[()=>n.e(2124).then(n.bind(n,4752)),"@site/versioned_docs/version-1.0.0/04-internal-API.md",4752],c2f60cfc:[()=>n.e(5868).then(n.bind(n,4848)),"@site/versioned_docs/version-1.0.0/checker-resource-leak-lab.md",4848],c359af60:[()=>n.e(8544).then(n.bind(n,7872)),"@site/docs/all-issue-types.md",7872],c412bf64:[()=>n.e(8608).then(n.bind(n,2116)),"@site/blog/2016-03-17-collaboration-with-spotify.md",2116],c4f5d8e4:[()=>Promise.all([n.e(2176),n.e(2632)]).then(n.bind(n,7540)),"@site/src/pages/index.js",7540],c71502c9:[()=>n.e(5388).then(n.bind(n,1851)),"@site/versioned_docs/version-1.0.0/checker-litho-required-props.md",1851],c7401661:[()=>n.e(1440).then(n.bind(n,9544)),"@site/versioned_docs/version-1.0.0/checker-pulse.md",9544],c8131338:[()=>n.e(9412).then(n.bind(n,1580)),"@site/docs/01-analyzing-apps-or-projects.md",1580],c8a5dae5:[()=>n.e(5516).then(n.bind(n,3393)),"@site/versioned_docs/version-1.1.0/checker-siof.md",3393],ca86781b:[()=>n.e(4856).then(n.bind(n,3916)),"@site/docs/all-checkers.md",3916],cb9da62d:[()=>n.e(7568).then(n.bind(n,1368)),"@site/versioned_docs/version-1.0.0/man-infer-report.md",1368],cbb882cb:[()=>n.e(3448).then(n.bind(n,6580)),"@site/versioned_docs/version-1.0.0/checker-bufferoverrun.md",6580],ccc49370:[()=>Promise.all([n.e(2176),n.e(9116),n.e(606),n.e(6344)]).then(n.bind(n,8320)),"@theme/BlogPostPage",8320],cd83de9e:[()=>n.e(956).then(n.bind(n,6628)),"@site/versioned_docs/version-1.1.0/checker-loop-hoisting.md",6628],ceca19cd:[()=>n.e(980).then(n.bind(n,9716)),"@site/versioned_docs/version-1.0.0/checker-quandary.md",9716],d47ba782:[()=>n.e(9198).then(n.bind(n,5164)),"@site/blog/2015-05-22-Infer-on-open-source-android-apps.md",5164],d9e16301:[()=>n.e(1728).then(n.bind(n,9036)),"@site/docs/support.md",9036],da41ed28:[()=>n.e(5192).then(n.bind(n,5324)),"@site/versioned_docs/version-1.1.0/versions.md",5324],dc4598d0:[()=>n.e(1292).then(n.bind(n,960)),"@site/versioned_docs/version-1.0.0/checker-fragment-retains-view.md",960],ddb8503b:[()=>n.e(3104).then(n.bind(n,7008)),"@site/versioned_docs/version-1.0.0/man-infer.md",7008],def5ef2c:[()=>n.e(3016).then(n.bind(n,5868)),"@site/versioned_docs/version-1.0.0/support.md",5868],df12ff2a:[()=>n.e(6068).then(n.bind(n,5912)),"@site/docs/checker-impurity.md",5912],df53045f:[()=>n.e(7136).then(n.bind(n,5300)),"@site/versioned_docs/version-1.0.0/checker-siof.md",5300],e0f83a1d:[()=>n.e(9032).then(n.bind(n,6816)),"@site/versioned_docs/version-1.1.0/00-hello-world.md",6816],e15bcb33:[()=>n.e(1240).then(n.t.bind(n,6632,19)),"~docs/default/version-1-1-0-metadata-prop-2f9.json",6632],e2e89445:[()=>n.e(1116).then(n.bind(n,8148)),"@site/versioned_docs/version-1.0.0/checker-linters.md",8148],e305a15c:[()=>n.e(8263).then(n.bind(n,2136)),"@site/versioned_docs/version-1.1.0/man-infer-run.md",2136],e436f9fb:[()=>n.e(9396).then(n.bind(n,2216)),"@site/docs/checker-loop-hoisting.md",2216],e44e3f47:[()=>n.e(112).then(n.bind(n,9128)),"@site/versioned_docs/version-1.1.0/checker-inefficient-keyset-iterator.md",9128],e66621bc:[()=>n.e(3600).then(n.bind(n,6700)),"@site/versioned_docs/version-1.1.0/checker-annotation-reachability.md",6700],e6b91a21:[()=>n.e(8601).then(n.bind(n,7272)),"@site/docs/checker-datalog.md",7272],e6b9ef91:[()=>n.e(3280).then(n.bind(n,2836)),"@site/versioned_docs/version-1.1.0/checker-purity.md",2836],e9325e77:[()=>n.e(9656).then(n.bind(n,5860)),"@site/docs/checker-topl.md",5860],eb0c92c1:[()=>n.e(5920).then(n.bind(n,7108)),"@site/versioned_docs/version-1.1.0/checker-racerd.md",7108],f278ac2c:[()=>n.e(3200).then(n.bind(n,2636)),"@site/versioned_docs/version-1.0.0/01-analyzing-apps-or-projects.md",2636],f5711d0d:[()=>n.e(2448).then(n.bind(n,1548)),"@site/versioned_docs/version-1.0.0/checker-impurity.md",1548],f5cfbeab:[()=>n.e(6680).then(n.bind(n,4320)),"@site/versioned_docs/version-1.0.0/checker-config-checks-between-markers.md",4320],f5ff54f0:[()=>n.e(724).then(n.bind(n,1512)),"@site/blog/2016-03-17-collaboration-with-spotify.md?truncated=true",1512],f769b3fd:[()=>n.e(4440).then(n.bind(n,3100)),"@site/docs/checker-config-impact-analysis.md",3100],f8092feb:[()=>n.e(1692).then(n.bind(n,2040)),"@site/versioned_docs/version-1.1.0/checker-immutable-cast.md",2040],fa38ac94:[()=>n.e(3292).then(n.bind(n,8788)),"@site/docs/checker-racerd.md",8788],fa9ab54d:[()=>n.e(3372).then(n.bind(n,3396)),"@site/blog/2016-11-28-atscale16.md",3396],fe661d8a:[()=>n.e(4020).then(n.bind(n,5468)),"@site/versioned_docs/version-1.0.0/checker-eradicate.md",5468],ff0352e3:[()=>n.e(6952).then(n.t.bind(n,4684,19)),"/home/runner/work/infer/infer/website/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",4684]};var s=n(7624);function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var l=n(8120),u=n(5548);function d(e,t){if("*"===e)return o()({loading:c,loader:()=>n.e(4552).then(n.bind(n,4552)),modules:["@theme/NotFound"],webpack:()=>[4552],render(e,t){const n=e.default;return(0,s.jsx)(u.Y,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=a[e+"-"+t],d={},p=[],f=[],h=(0,l.c)(r);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:c,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error("The page component at "+e+" doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.");"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;return delete o.__context,(0,s.jsx)(u.Y,{value:i,children:(0,s.jsx)(a,{...o,...n})})}})}const p=[{path:"/blog",component:d("/blog","4a5"),exact:!0},{path:"/blog/2015/05/22/Infer-on-open-source-android-apps",component:d("/blog/2015/05/22/Infer-on-open-source-android-apps","b8c"),exact:!0},{path:"/blog/2016/03/17/collaboration-with-spotify",component:d("/blog/2016/03/17/collaboration-with-spotify","139"),exact:!0},{path:"/blog/2016/04/07/mobileatscale-london-talk",component:d("/blog/2016/04/07/mobileatscale-london-talk","47c"),exact:!0},{path:"/blog/2016/06/23/first-opensourceversary",component:d("/blog/2016/06/23/first-opensourceversary","986"),exact:!0},{path:"/blog/2016/08/30/curryon-rome-talk",component:d("/blog/2016/08/30/curryon-rome-talk","d83"),exact:!0},{path:"/blog/2016/11/28/atscale16",component:d("/blog/2016/11/28/atscale16","103"),exact:!0},{path:"/blog/2017/10/20/ocamlformat-released",component:d("/blog/2017/10/20/ocamlformat-released","07d"),exact:!0},{path:"/blog/archive",component:d("/blog/archive","0f9"),exact:!0},{path:"/search",component:d("/search","6d2"),exact:!0},{path:"/docs",component:d("/docs","5c9"),routes:[{path:"/docs/1.0.0",component:d("/docs/1.0.0","5d3"),routes:[{path:"/docs/1.0.0",component:d("/docs/1.0.0","678"),routes:[{path:"/docs/1.0.0/about-Infer",component:d("/docs/1.0.0/about-Infer","b9d"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/absint-framework",component:d("/docs/1.0.0/absint-framework","e0a"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/advanced-features",component:d("/docs/1.0.0/advanced-features","66b"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/all-issue-types",component:d("/docs/1.0.0/all-issue-types","51e"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/analyzing-apps-or-projects",component:d("/docs/1.0.0/analyzing-apps-or-projects","82e"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-annotation-reachability",component:d("/docs/1.0.0/checker-annotation-reachability","139"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-biabduction",component:d("/docs/1.0.0/checker-biabduction","a6a"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-bufferoverrun",component:d("/docs/1.0.0/checker-bufferoverrun","998"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-config-checks-between-markers",component:d("/docs/1.0.0/checker-config-checks-between-markers","1a2"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-cost",component:d("/docs/1.0.0/checker-cost","257"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-eradicate",component:d("/docs/1.0.0/checker-eradicate","414"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-fragment-retains-view",component:d("/docs/1.0.0/checker-fragment-retains-view","c4c"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-immutable-cast",component:d("/docs/1.0.0/checker-immutable-cast","7df"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-impurity",component:d("/docs/1.0.0/checker-impurity","2bb"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-inefficient-keyset-iterator",component:d("/docs/1.0.0/checker-inefficient-keyset-iterator","c58"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-linters",component:d("/docs/1.0.0/checker-linters","5b0"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-litho-required-props",component:d("/docs/1.0.0/checker-litho-required-props","c6c"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-liveness",component:d("/docs/1.0.0/checker-liveness","242"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-loop-hoisting",component:d("/docs/1.0.0/checker-loop-hoisting","b90"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-printf-args",component:d("/docs/1.0.0/checker-printf-args","3c5"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-pulse",component:d("/docs/1.0.0/checker-pulse","3e3"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-purity",component:d("/docs/1.0.0/checker-purity","112"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-quandary",component:d("/docs/1.0.0/checker-quandary","1a8"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-racerd",component:d("/docs/1.0.0/checker-racerd","265"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-resource-leak-lab",component:d("/docs/1.0.0/checker-resource-leak-lab","abb"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-self-in-block",component:d("/docs/1.0.0/checker-self-in-block","d14"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-siof",component:d("/docs/1.0.0/checker-siof","ce7"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-starvation",component:d("/docs/1.0.0/checker-starvation","239"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-topl-biabd",component:d("/docs/1.0.0/checker-topl-biabd","753"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-topl-pulse",component:d("/docs/1.0.0/checker-topl-pulse","dce"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/checker-uninit",component:d("/docs/1.0.0/checker-uninit","e14"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/getting-started",component:d("/docs/1.0.0/getting-started","1a9"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/hello-world",component:d("/docs/1.0.0/hello-world","76d"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/infer-workflow",component:d("/docs/1.0.0/infer-workflow","136"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/internal-API",component:d("/docs/1.0.0/internal-API","3ef"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer",component:d("/docs/1.0.0/man-infer","b1e"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-analyze",component:d("/docs/1.0.0/man-infer-analyze","812"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-capture",component:d("/docs/1.0.0/man-infer-capture","ab4"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-compile",component:d("/docs/1.0.0/man-infer-compile","27a"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-debug",component:d("/docs/1.0.0/man-infer-debug","f4e"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-explore",component:d("/docs/1.0.0/man-infer-explore","c31"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-help",component:d("/docs/1.0.0/man-infer-help","8f2"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-report",component:d("/docs/1.0.0/man-infer-report","3a4"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-reportdiff",component:d("/docs/1.0.0/man-infer-reportdiff","7df"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-infer-run",component:d("/docs/1.0.0/man-infer-run","5ce"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/man-pages",component:d("/docs/1.0.0/man-pages","e51"),exact:!0},{path:"/docs/1.0.0/separation-logic-and-bi-abduction",component:d("/docs/1.0.0/separation-logic-and-bi-abduction","616"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/steps-for-ci",component:d("/docs/1.0.0/steps-for-ci","60c"),exact:!0,sidebar:"docs"},{path:"/docs/1.0.0/support",component:d("/docs/1.0.0/support","326"),exact:!0},{path:"/docs/1.0.0/versions",component:d("/docs/1.0.0/versions","87d"),exact:!0,sidebar:"docs"}]}]},{path:"/docs/next",component:d("/docs/next","76e"),routes:[{path:"/docs/next",component:d("/docs/next","34c"),routes:[{path:"/docs/next/about-Infer",component:d("/docs/next/about-Infer","3ed"),exact:!0,sidebar:"docs"},{path:"/docs/next/absint-framework",component:d("/docs/next/absint-framework","c39"),exact:!0,sidebar:"docs"},{path:"/docs/next/all-checkers",component:d("/docs/next/all-checkers","f32"),exact:!0,sidebar:"docs"},{path:"/docs/next/all-issue-types",component:d("/docs/next/all-issue-types","2fc"),exact:!0,sidebar:"docs"},{path:"/docs/next/analyzing-apps-or-projects",component:d("/docs/next/analyzing-apps-or-projects","6ab"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-annotation-reachability",component:d("/docs/next/checker-annotation-reachability","2cc"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-biabduction",component:d("/docs/next/checker-biabduction","075"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-bufferoverrun",component:d("/docs/next/checker-bufferoverrun","3cf"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-config-impact-analysis",component:d("/docs/next/checker-config-impact-analysis","4b3"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-cost",component:d("/docs/next/checker-cost","736"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-datalog",component:d("/docs/next/checker-datalog","a7e"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-fragment-retains-view",component:d("/docs/next/checker-fragment-retains-view","7ef"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-impurity",component:d("/docs/next/checker-impurity","e45"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-inefficient-keyset-iterator",component:d("/docs/next/checker-inefficient-keyset-iterator","62c"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-lineage",component:d("/docs/next/checker-lineage","eba"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-litho-required-props",component:d("/docs/next/checker-litho-required-props","243"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-liveness",component:d("/docs/next/checker-liveness","942"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-loop-hoisting",component:d("/docs/next/checker-loop-hoisting","34f"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-parameter-not-null-checked",component:d("/docs/next/checker-parameter-not-null-checked","433"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-printf-args",component:d("/docs/next/checker-printf-args","07b"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-pulse",component:d("/docs/next/checker-pulse","369"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-purity",component:d("/docs/next/checker-purity","4d2"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-quandary",component:d("/docs/next/checker-quandary","a3c"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-racerd",component:d("/docs/next/checker-racerd","977"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-resource-leak-lab",component:d("/docs/next/checker-resource-leak-lab","44d"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-scope-leakage",component:d("/docs/next/checker-scope-leakage","6dd"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-self-in-block",component:d("/docs/next/checker-self-in-block","590"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-sil-validation",component:d("/docs/next/checker-sil-validation","af7"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-siof",component:d("/docs/next/checker-siof","e35"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-starvation",component:d("/docs/next/checker-starvation","69f"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-topl",component:d("/docs/next/checker-topl","e90"),exact:!0,sidebar:"docs"},{path:"/docs/next/checker-uninit",component:d("/docs/next/checker-uninit","725"),exact:!0,sidebar:"docs"},{path:"/docs/next/getting-started",component:d("/docs/next/getting-started","bb6"),exact:!0,sidebar:"docs"},{path:"/docs/next/hello-world",component:d("/docs/next/hello-world","278"),exact:!0,sidebar:"docs"},{path:"/docs/next/infer-workflow",component:d("/docs/next/infer-workflow","98a"),exact:!0,sidebar:"docs"},{path:"/docs/next/internal-API",component:d("/docs/next/internal-API","91a"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer",component:d("/docs/next/man-infer","e41"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-analyze",component:d("/docs/next/man-infer-analyze","918"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-capture",component:d("/docs/next/man-infer-capture","098"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-compile",component:d("/docs/next/man-infer-compile","f52"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-debug",component:d("/docs/next/man-infer-debug","ff5"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-explore",component:d("/docs/next/man-infer-explore","70d"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-help",component:d("/docs/next/man-infer-help","0f0"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-report",component:d("/docs/next/man-infer-report","601"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-reportdiff",component:d("/docs/next/man-infer-reportdiff","fd3"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-infer-run",component:d("/docs/next/man-infer-run","a24"),exact:!0,sidebar:"docs"},{path:"/docs/next/man-pages",component:d("/docs/next/man-pages","d30"),exact:!0},{path:"/docs/next/separation-logic-and-bi-abduction",component:d("/docs/next/separation-logic-and-bi-abduction","b95"),exact:!0,sidebar:"docs"},{path:"/docs/next/steps-for-ci",component:d("/docs/next/steps-for-ci","400"),exact:!0,sidebar:"docs"},{path:"/docs/next/support",component:d("/docs/next/support","104"),exact:!0},{path:"/docs/next/versions",component:d("/docs/next/versions","822"),exact:!0,sidebar:"docs"}]}]},{path:"/docs",component:d("/docs","65a"),routes:[{path:"/docs",component:d("/docs","530"),routes:[{path:"/docs/about-Infer",component:d("/docs/about-Infer","802"),exact:!0,sidebar:"docs"},{path:"/docs/absint-framework",component:d("/docs/absint-framework","767"),exact:!0,sidebar:"docs"},{path:"/docs/all-issue-types",component:d("/docs/all-issue-types","2b2"),exact:!0,sidebar:"docs"},{path:"/docs/analyzing-apps-or-projects",component:d("/docs/analyzing-apps-or-projects","016"),exact:!0,sidebar:"docs"},{path:"/docs/checker-annotation-reachability",component:d("/docs/checker-annotation-reachability","671"),exact:!0,sidebar:"docs"},{path:"/docs/checker-biabduction",component:d("/docs/checker-biabduction","d74"),exact:!0,sidebar:"docs"},{path:"/docs/checker-bufferoverrun",component:d("/docs/checker-bufferoverrun","660"),exact:!0,sidebar:"docs"},{path:"/docs/checker-config-checks-between-markers",component:d("/docs/checker-config-checks-between-markers","0c7"),exact:!0,sidebar:"docs"},{path:"/docs/checker-config-impact-analysis",component:d("/docs/checker-config-impact-analysis","939"),exact:!0,sidebar:"docs"},{path:"/docs/checker-cost",component:d("/docs/checker-cost","39f"),exact:!0,sidebar:"docs"},{path:"/docs/checker-dotnet-resource-leak",component:d("/docs/checker-dotnet-resource-leak","641"),exact:!0,sidebar:"docs"},{path:"/docs/checker-eradicate",component:d("/docs/checker-eradicate","a10"),exact:!0,sidebar:"docs"},{path:"/docs/checker-fragment-retains-view",component:d("/docs/checker-fragment-retains-view","2f2"),exact:!0,sidebar:"docs"},{path:"/docs/checker-immutable-cast",component:d("/docs/checker-immutable-cast","c3f"),exact:!0,sidebar:"docs"},{path:"/docs/checker-impurity",component:d("/docs/checker-impurity","bde"),exact:!0,sidebar:"docs"},{path:"/docs/checker-inefficient-keyset-iterator",component:d("/docs/checker-inefficient-keyset-iterator","aa4"),exact:!0,sidebar:"docs"},{path:"/docs/checker-linters",component:d("/docs/checker-linters","e34"),exact:!0,sidebar:"docs"},{path:"/docs/checker-litho-required-props",component:d("/docs/checker-litho-required-props","7af"),exact:!0,sidebar:"docs"},{path:"/docs/checker-liveness",component:d("/docs/checker-liveness","aab"),exact:!0,sidebar:"docs"},{path:"/docs/checker-loop-hoisting",component:d("/docs/checker-loop-hoisting","c40"),exact:!0,sidebar:"docs"},{path:"/docs/checker-printf-args",component:d("/docs/checker-printf-args","25e"),exact:!0,sidebar:"docs"},{path:"/docs/checker-pulse",component:d("/docs/checker-pulse","7ac"),exact:!0,sidebar:"docs"},{path:"/docs/checker-purity",component:d("/docs/checker-purity","264"),exact:!0,sidebar:"docs"},{path:"/docs/checker-quandary",component:d("/docs/checker-quandary","e3c"),exact:!0,sidebar:"docs"},{path:"/docs/checker-racerd",component:d("/docs/checker-racerd","2c2"),exact:!0,sidebar:"docs"},{path:"/docs/checker-resource-leak-lab",component:d("/docs/checker-resource-leak-lab","f06"),exact:!0,sidebar:"docs"},{path:"/docs/checker-self-in-block",component:d("/docs/checker-self-in-block","04d"),exact:!0,sidebar:"docs"},{path:"/docs/checker-siof",component:d("/docs/checker-siof","8e1"),exact:!0,sidebar:"docs"},{path:"/docs/checker-starvation",component:d("/docs/checker-starvation","8ca"),exact:!0,sidebar:"docs"},{path:"/docs/checker-topl",component:d("/docs/checker-topl","3a9"),exact:!0,sidebar:"docs"},{path:"/docs/checker-uninit",component:d("/docs/checker-uninit","9ba"),exact:!0,sidebar:"docs"},{path:"/docs/getting-started",component:d("/docs/getting-started","73e"),exact:!0,sidebar:"docs"},{path:"/docs/hello-world",component:d("/docs/hello-world","c5e"),exact:!0,sidebar:"docs"},{path:"/docs/infer-workflow",component:d("/docs/infer-workflow","d95"),exact:!0,sidebar:"docs"},{path:"/docs/internal-API",component:d("/docs/internal-API","9a0"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer",component:d("/docs/man-infer","0d0"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-analyze",component:d("/docs/man-infer-analyze","c47"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-capture",component:d("/docs/man-infer-capture","d4b"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-compile",component:d("/docs/man-infer-compile","7a0"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-debug",component:d("/docs/man-infer-debug","6cb"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-explore",component:d("/docs/man-infer-explore","ba9"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-help",component:d("/docs/man-infer-help","353"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-report",component:d("/docs/man-infer-report","fdf"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-reportdiff",component:d("/docs/man-infer-reportdiff","df3"),exact:!0,sidebar:"docs"},{path:"/docs/man-infer-run",component:d("/docs/man-infer-run","3bf"),exact:!0,sidebar:"docs"},{path:"/docs/man-pages",component:d("/docs/man-pages","fd1"),exact:!0},{path:"/docs/separation-logic-and-bi-abduction",component:d("/docs/separation-logic-and-bi-abduction","ec0"),exact:!0,sidebar:"docs"},{path:"/docs/steps-for-ci",component:d("/docs/steps-for-ci","a90"),exact:!0,sidebar:"docs"},{path:"/docs/support",component:d("/docs/support","8d4"),exact:!0},{path:"/docs/versions",component:d("/docs/versions","ffe"),exact:!0,sidebar:"docs"}]}]}]},{path:"/",component:d("/","e6a"),exact:!0},{path:"*",component:d("*")}]},240:(e,t,n)=>{"use strict";n.d(t,{e:()=>a,g:()=>i});var r=n(1504),o=n(7624);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8808:(e,t,n)=>{"use strict";var r=n(1504),o=n(8352),a=n(440),i=n(2160),s=n(8684);const c=[n(7483),n(1462),n(5396),n(1976),n(1496)];var l=n(628),u=n(5592),d=n(5464),p=n(7624);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var h=n(6952),m=n(8264),g=n(964),b=n(1824),y=n(5008),v=n(1616),k=n(204),x=n(4456),w=n(5684),_=n(8712);function S(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,m.c)(),r=(0,v.D)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,p.jsxs)(h.c,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},"meta-og-"+e.htmlLang)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.c)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,m.c)(),{pathname:r}=(0,u.IT)();return e+(0,w.applyTrailingSlash)((0,g.c)(r),{trailingSlash:n,baseUrl:t})}(),o=t?""+n+t:r;return(0,p.jsxs)(h.c,{children:[(0,p.jsx)("meta",{property:"og:url",content:o}),(0,p.jsx)("link",{rel:"canonical",href:o})]})}function C(){const{i18n:{currentLocale:e}}=(0,m.c)(),{metadata:t,image:n}=(0,b.y)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(h.c,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:k.m})]}),n&&(0,p.jsx)(y.U7,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(S,{}),(0,p.jsx)(_.c,{tag:x.e6,locale:e}),(0,p.jsx)(h.c,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const T=new Map;function A(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.C)(l.c,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var j=n(240),N=n(136),L=n(5288);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{var r,o;const a=null!=(r=null==(o=t.default)?void 0:o[e])?r:t[e];return null==a?void 0:a(...n)}));return()=>o.forEach((e=>null==e?void 0:e()))}const O=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,L.c)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);null==t||t.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),P("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function R(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.C)(l.c,e))).flat();return Promise.all(t.map((e=>null==e.route.component.preload?void 0:e.route.component.preload())))}class I extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=s.c.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),R(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(O,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.kX,{location:t,render:()=>e})})}}const M=I,F="__docusaurus-base-url-issue-banner-container",D="__docusaurus-base-url-issue-banner",z="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return"\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '"+F+"';\n var bannerHtml = "+JSON.stringify(function(e){return'\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = '+e+" "+("/"===e?" (default value)":"")+'

\n

We suggest trying baseUrl =

\n
\n'}(e)).replace(/{var r,o;if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();const i=null!=(r=document.getElementsByTagName("head")[0])?r:null==(o=document.getElementsByName("script")[0])?void 0:o.parentNode;null==i||i.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Q=n(8120);const Z=new Set,X=new Set,J=()=>{var e,t;return(null==(e=navigator.connection)?void 0:e.effectiveType.includes("2g"))||(null==(t=navigator.connection)?void 0:t.saveData)},ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Z.has(e))(e))return!1;Z.add(e);const t=(0,d.C)(l.c,e).flatMap((e=>{return t=e.route.path,Object.entries(Y).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Q.c)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?K(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),R(e))},te=Object.freeze(ee),ne=Boolean(!0);if(s.c.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.EN,{children:(0,p.jsx)(a.kn,{children:(0,p.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(ne)r.startTransition((()=>{o.hydrateRoot(e,t,{onRecoverableError:n})}));else{const a=o.createRoot(e,{onRecoverableError:n});r.startTransition((()=>{a.render(t)}))}};R(window.location.pathname).then(s)}},136:(e,t,n)=>{"use strict";n.d(t,{e:()=>d,y:()=>p});var r=n(1504),o=n(7768);const a=JSON.parse('{"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-6T8Z3855RZ"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":false,"path":"/docs/next","mainDocId":"getting-started","docs":[{"id":"about-Infer","path":"/docs/next/about-Infer","sidebar":"docs"},{"id":"absint-framework","path":"/docs/next/absint-framework","sidebar":"docs"},{"id":"all-checkers","path":"/docs/next/all-checkers","sidebar":"docs"},{"id":"all-issue-types","path":"/docs/next/all-issue-types","sidebar":"docs"},{"id":"analyzing-apps-or-projects","path":"/docs/next/analyzing-apps-or-projects","sidebar":"docs"},{"id":"checker-annotation-reachability","path":"/docs/next/checker-annotation-reachability","sidebar":"docs"},{"id":"checker-biabduction","path":"/docs/next/checker-biabduction","sidebar":"docs"},{"id":"checker-bufferoverrun","path":"/docs/next/checker-bufferoverrun","sidebar":"docs"},{"id":"checker-config-impact-analysis","path":"/docs/next/checker-config-impact-analysis","sidebar":"docs"},{"id":"checker-cost","path":"/docs/next/checker-cost","sidebar":"docs"},{"id":"checker-datalog","path":"/docs/next/checker-datalog","sidebar":"docs"},{"id":"checker-fragment-retains-view","path":"/docs/next/checker-fragment-retains-view","sidebar":"docs"},{"id":"checker-impurity","path":"/docs/next/checker-impurity","sidebar":"docs"},{"id":"checker-inefficient-keyset-iterator","path":"/docs/next/checker-inefficient-keyset-iterator","sidebar":"docs"},{"id":"checker-lineage","path":"/docs/next/checker-lineage","sidebar":"docs"},{"id":"checker-litho-required-props","path":"/docs/next/checker-litho-required-props","sidebar":"docs"},{"id":"checker-liveness","path":"/docs/next/checker-liveness","sidebar":"docs"},{"id":"checker-loop-hoisting","path":"/docs/next/checker-loop-hoisting","sidebar":"docs"},{"id":"checker-parameter-not-null-checked","path":"/docs/next/checker-parameter-not-null-checked","sidebar":"docs"},{"id":"checker-printf-args","path":"/docs/next/checker-printf-args","sidebar":"docs"},{"id":"checker-pulse","path":"/docs/next/checker-pulse","sidebar":"docs"},{"id":"checker-purity","path":"/docs/next/checker-purity","sidebar":"docs"},{"id":"checker-quandary","path":"/docs/next/checker-quandary","sidebar":"docs"},{"id":"checker-racerd","path":"/docs/next/checker-racerd","sidebar":"docs"},{"id":"checker-resource-leak-lab","path":"/docs/next/checker-resource-leak-lab","sidebar":"docs"},{"id":"checker-scope-leakage","path":"/docs/next/checker-scope-leakage","sidebar":"docs"},{"id":"checker-self-in-block","path":"/docs/next/checker-self-in-block","sidebar":"docs"},{"id":"checker-sil-validation","path":"/docs/next/checker-sil-validation","sidebar":"docs"},{"id":"checker-siof","path":"/docs/next/checker-siof","sidebar":"docs"},{"id":"checker-starvation","path":"/docs/next/checker-starvation","sidebar":"docs"},{"id":"checker-topl","path":"/docs/next/checker-topl","sidebar":"docs"},{"id":"checker-uninit","path":"/docs/next/checker-uninit","sidebar":"docs"},{"id":"getting-started","path":"/docs/next/getting-started","sidebar":"docs"},{"id":"hello-world","path":"/docs/next/hello-world","sidebar":"docs"},{"id":"infer-workflow","path":"/docs/next/infer-workflow","sidebar":"docs"},{"id":"internal-API","path":"/docs/next/internal-API","sidebar":"docs"},{"id":"man-infer","path":"/docs/next/man-infer","sidebar":"docs"},{"id":"man-infer-analyze","path":"/docs/next/man-infer-analyze","sidebar":"docs"},{"id":"man-infer-capture","path":"/docs/next/man-infer-capture","sidebar":"docs"},{"id":"man-infer-compile","path":"/docs/next/man-infer-compile","sidebar":"docs"},{"id":"man-infer-debug","path":"/docs/next/man-infer-debug","sidebar":"docs"},{"id":"man-infer-explore","path":"/docs/next/man-infer-explore","sidebar":"docs"},{"id":"man-infer-help","path":"/docs/next/man-infer-help","sidebar":"docs"},{"id":"man-infer-report","path":"/docs/next/man-infer-report","sidebar":"docs"},{"id":"man-infer-reportdiff","path":"/docs/next/man-infer-reportdiff","sidebar":"docs"},{"id":"man-infer-run","path":"/docs/next/man-infer-run","sidebar":"docs"},{"id":"man-pages","path":"/docs/next/man-pages"},{"id":"separation-logic-and-bi-abduction","path":"/docs/next/separation-logic-and-bi-abduction","sidebar":"docs"},{"id":"steps-for-ci","path":"/docs/next/steps-for-ci","sidebar":"docs"},{"id":"support","path":"/docs/next/support"},{"id":"versions","path":"/docs/next/versions","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/docs/next/getting-started","label":"getting-started"}}}},{"name":"1.1.0","label":"1.1.0","isLast":true,"path":"/docs","mainDocId":"getting-started","docs":[{"id":"about-Infer","path":"/docs/about-Infer","sidebar":"docs"},{"id":"absint-framework","path":"/docs/absint-framework","sidebar":"docs"},{"id":"all-issue-types","path":"/docs/all-issue-types","sidebar":"docs"},{"id":"analyzing-apps-or-projects","path":"/docs/analyzing-apps-or-projects","sidebar":"docs"},{"id":"checker-annotation-reachability","path":"/docs/checker-annotation-reachability","sidebar":"docs"},{"id":"checker-biabduction","path":"/docs/checker-biabduction","sidebar":"docs"},{"id":"checker-bufferoverrun","path":"/docs/checker-bufferoverrun","sidebar":"docs"},{"id":"checker-config-checks-between-markers","path":"/docs/checker-config-checks-between-markers","sidebar":"docs"},{"id":"checker-config-impact-analysis","path":"/docs/checker-config-impact-analysis","sidebar":"docs"},{"id":"checker-cost","path":"/docs/checker-cost","sidebar":"docs"},{"id":"checker-dotnet-resource-leak","path":"/docs/checker-dotnet-resource-leak","sidebar":"docs"},{"id":"checker-eradicate","path":"/docs/checker-eradicate","sidebar":"docs"},{"id":"checker-fragment-retains-view","path":"/docs/checker-fragment-retains-view","sidebar":"docs"},{"id":"checker-immutable-cast","path":"/docs/checker-immutable-cast","sidebar":"docs"},{"id":"checker-impurity","path":"/docs/checker-impurity","sidebar":"docs"},{"id":"checker-inefficient-keyset-iterator","path":"/docs/checker-inefficient-keyset-iterator","sidebar":"docs"},{"id":"checker-linters","path":"/docs/checker-linters","sidebar":"docs"},{"id":"checker-litho-required-props","path":"/docs/checker-litho-required-props","sidebar":"docs"},{"id":"checker-liveness","path":"/docs/checker-liveness","sidebar":"docs"},{"id":"checker-loop-hoisting","path":"/docs/checker-loop-hoisting","sidebar":"docs"},{"id":"checker-printf-args","path":"/docs/checker-printf-args","sidebar":"docs"},{"id":"checker-pulse","path":"/docs/checker-pulse","sidebar":"docs"},{"id":"checker-purity","path":"/docs/checker-purity","sidebar":"docs"},{"id":"checker-quandary","path":"/docs/checker-quandary","sidebar":"docs"},{"id":"checker-racerd","path":"/docs/checker-racerd","sidebar":"docs"},{"id":"checker-resource-leak-lab","path":"/docs/checker-resource-leak-lab","sidebar":"docs"},{"id":"checker-self-in-block","path":"/docs/checker-self-in-block","sidebar":"docs"},{"id":"checker-siof","path":"/docs/checker-siof","sidebar":"docs"},{"id":"checker-starvation","path":"/docs/checker-starvation","sidebar":"docs"},{"id":"checker-topl","path":"/docs/checker-topl","sidebar":"docs"},{"id":"checker-uninit","path":"/docs/checker-uninit","sidebar":"docs"},{"id":"getting-started","path":"/docs/getting-started","sidebar":"docs"},{"id":"hello-world","path":"/docs/hello-world","sidebar":"docs"},{"id":"infer-workflow","path":"/docs/infer-workflow","sidebar":"docs"},{"id":"internal-API","path":"/docs/internal-API","sidebar":"docs"},{"id":"man-infer","path":"/docs/man-infer","sidebar":"docs"},{"id":"man-infer-analyze","path":"/docs/man-infer-analyze","sidebar":"docs"},{"id":"man-infer-capture","path":"/docs/man-infer-capture","sidebar":"docs"},{"id":"man-infer-compile","path":"/docs/man-infer-compile","sidebar":"docs"},{"id":"man-infer-debug","path":"/docs/man-infer-debug","sidebar":"docs"},{"id":"man-infer-explore","path":"/docs/man-infer-explore","sidebar":"docs"},{"id":"man-infer-help","path":"/docs/man-infer-help","sidebar":"docs"},{"id":"man-infer-report","path":"/docs/man-infer-report","sidebar":"docs"},{"id":"man-infer-reportdiff","path":"/docs/man-infer-reportdiff","sidebar":"docs"},{"id":"man-infer-run","path":"/docs/man-infer-run","sidebar":"docs"},{"id":"man-pages","path":"/docs/man-pages"},{"id":"separation-logic-and-bi-abduction","path":"/docs/separation-logic-and-bi-abduction","sidebar":"docs"},{"id":"steps-for-ci","path":"/docs/steps-for-ci","sidebar":"docs"},{"id":"support","path":"/docs/support"},{"id":"versions","path":"/docs/versions","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/docs/getting-started","label":"getting-started"}}}},{"name":"1.0.0","label":"1.0.0","isLast":false,"path":"/docs/1.0.0","mainDocId":"getting-started","docs":[{"id":"about-Infer","path":"/docs/1.0.0/about-Infer","sidebar":"docs"},{"id":"absint-framework","path":"/docs/1.0.0/absint-framework","sidebar":"docs"},{"id":"advanced-features","path":"/docs/1.0.0/advanced-features","sidebar":"docs"},{"id":"all-issue-types","path":"/docs/1.0.0/all-issue-types","sidebar":"docs"},{"id":"analyzing-apps-or-projects","path":"/docs/1.0.0/analyzing-apps-or-projects","sidebar":"docs"},{"id":"checker-annotation-reachability","path":"/docs/1.0.0/checker-annotation-reachability","sidebar":"docs"},{"id":"checker-biabduction","path":"/docs/1.0.0/checker-biabduction","sidebar":"docs"},{"id":"checker-bufferoverrun","path":"/docs/1.0.0/checker-bufferoverrun","sidebar":"docs"},{"id":"checker-config-checks-between-markers","path":"/docs/1.0.0/checker-config-checks-between-markers","sidebar":"docs"},{"id":"checker-cost","path":"/docs/1.0.0/checker-cost","sidebar":"docs"},{"id":"checker-eradicate","path":"/docs/1.0.0/checker-eradicate","sidebar":"docs"},{"id":"checker-fragment-retains-view","path":"/docs/1.0.0/checker-fragment-retains-view","sidebar":"docs"},{"id":"checker-immutable-cast","path":"/docs/1.0.0/checker-immutable-cast","sidebar":"docs"},{"id":"checker-impurity","path":"/docs/1.0.0/checker-impurity","sidebar":"docs"},{"id":"checker-inefficient-keyset-iterator","path":"/docs/1.0.0/checker-inefficient-keyset-iterator","sidebar":"docs"},{"id":"checker-linters","path":"/docs/1.0.0/checker-linters","sidebar":"docs"},{"id":"checker-litho-required-props","path":"/docs/1.0.0/checker-litho-required-props","sidebar":"docs"},{"id":"checker-liveness","path":"/docs/1.0.0/checker-liveness","sidebar":"docs"},{"id":"checker-loop-hoisting","path":"/docs/1.0.0/checker-loop-hoisting","sidebar":"docs"},{"id":"checker-printf-args","path":"/docs/1.0.0/checker-printf-args","sidebar":"docs"},{"id":"checker-pulse","path":"/docs/1.0.0/checker-pulse","sidebar":"docs"},{"id":"checker-purity","path":"/docs/1.0.0/checker-purity","sidebar":"docs"},{"id":"checker-quandary","path":"/docs/1.0.0/checker-quandary","sidebar":"docs"},{"id":"checker-racerd","path":"/docs/1.0.0/checker-racerd","sidebar":"docs"},{"id":"checker-resource-leak-lab","path":"/docs/1.0.0/checker-resource-leak-lab","sidebar":"docs"},{"id":"checker-self-in-block","path":"/docs/1.0.0/checker-self-in-block","sidebar":"docs"},{"id":"checker-siof","path":"/docs/1.0.0/checker-siof","sidebar":"docs"},{"id":"checker-starvation","path":"/docs/1.0.0/checker-starvation","sidebar":"docs"},{"id":"checker-topl-biabd","path":"/docs/1.0.0/checker-topl-biabd","sidebar":"docs"},{"id":"checker-topl-pulse","path":"/docs/1.0.0/checker-topl-pulse","sidebar":"docs"},{"id":"checker-uninit","path":"/docs/1.0.0/checker-uninit","sidebar":"docs"},{"id":"getting-started","path":"/docs/1.0.0/getting-started","sidebar":"docs"},{"id":"hello-world","path":"/docs/1.0.0/hello-world","sidebar":"docs"},{"id":"infer-workflow","path":"/docs/1.0.0/infer-workflow","sidebar":"docs"},{"id":"internal-API","path":"/docs/1.0.0/internal-API","sidebar":"docs"},{"id":"man-infer","path":"/docs/1.0.0/man-infer","sidebar":"docs"},{"id":"man-infer-analyze","path":"/docs/1.0.0/man-infer-analyze","sidebar":"docs"},{"id":"man-infer-capture","path":"/docs/1.0.0/man-infer-capture","sidebar":"docs"},{"id":"man-infer-compile","path":"/docs/1.0.0/man-infer-compile","sidebar":"docs"},{"id":"man-infer-debug","path":"/docs/1.0.0/man-infer-debug","sidebar":"docs"},{"id":"man-infer-explore","path":"/docs/1.0.0/man-infer-explore","sidebar":"docs"},{"id":"man-infer-help","path":"/docs/1.0.0/man-infer-help","sidebar":"docs"},{"id":"man-infer-report","path":"/docs/1.0.0/man-infer-report","sidebar":"docs"},{"id":"man-infer-reportdiff","path":"/docs/1.0.0/man-infer-reportdiff","sidebar":"docs"},{"id":"man-infer-run","path":"/docs/1.0.0/man-infer-run","sidebar":"docs"},{"id":"man-pages","path":"/docs/1.0.0/man-pages"},{"id":"separation-logic-and-bi-abduction","path":"/docs/1.0.0/separation-logic-and-bi-abduction","sidebar":"docs"},{"id":"steps-for-ci","path":"/docs/1.0.0/steps-for-ci","sidebar":"docs"},{"id":"support","path":"/docs/1.0.0/support"},{"id":"versions","path":"/docs/1.0.0/versions","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/docs/1.0.0/getting-started","label":"getting-started"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(144);const c=JSON.parse('{"docusaurusVersion":"3.1.1","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.1.1"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.1.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.1.1"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.1.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.1.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.1.1"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.1.1"}}}');var l=n(7624);const u={siteConfig:o.default,siteMetadata:c,globalData:a,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,l.jsx)(d.Provider,{value:u,children:t})}},5852:(e,t,n)=>{"use strict";n.d(t,{c:()=>f});var r=n(1504),o=n(8684),a=n(6952),i=n(5684),s=n(7468),c=n(7624);function l(e){let{error:t,tryAgain:n}=e;return(0,c.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,c.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,c.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,c.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,c.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,c.jsxs)(f,{fallback:()=>(0,c.jsx)(l,{error:t,tryAgain:n}),children:[(0,c.jsx)(a.c,{children:(0,c.jsx)("title",{children:"Page Error"})}),(0,c.jsx)(s.c,{children:(0,c.jsx)(l,{error:t,tryAgain:n})})]})}const p=e=>(0,c.jsx)(d,{...e});class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.c.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){var n;const e={error:t,tryAgain:()=>this.setState({error:null})};return(null!=(n=this.props.fallback)?n:p)(e)}return null!=e?e:null}}},8684:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},6952:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(2160),o=n(7624);function a(e){return(0,o.jsx)(r.So,{...e})}},867:(e,t,n)=>{"use strict";n.d(t,{c:()=>f});var r=n(1504),o=n(440),a=n(5684),i=n(8264),s=n(8136),c=n(8684),l=n(5976),u=n(964),d=n(7624);function p(e,t){var n,p;let{isNavLink:f,to:h,href:m,activeClassName:g,isActive:b,"data-noBrokenLinkCheck":y,autoAddBaseUrl:v=!0,...k}=e;const{siteConfig:{trailingSlash:x,baseUrl:w}}=(0,i.c)(),{withBaseUrl:_}=(0,u.E)(),S=(0,l.c)(),E=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>E.current));const C=h||m;const T=(0,s.c)(C),A=null==C?void 0:C.replace("pathname://","");let j=void 0!==A?(N=A,v&&(e=>e.startsWith("/"))(N)?_(N):N):void 0;var N;j&&T&&(j=(0,a.applyTrailingSlash)(j,{trailingSlash:x,baseUrl:w}));const L=(0,r.useRef)(!1),P=f?o.Af:o.cH,O=c.c.canUseIntersectionObserver,R=(0,r.useRef)(),I=()=>{L.current||null==j||(window.docusaurus.preload(j),L.current=!0)};(0,r.useEffect)((()=>(!O&&T&&null!=j&&window.docusaurus.prefetch(j),()=>{O&&R.current&&R.current.disconnect()})),[R,j,O,T]);const M=null!=(n=null==(p=j)?void 0:p.startsWith("#"))&&n,F=!k.target||"_self"===k.target,D=!j||!T||!F||M;return y||!M&&D||S.collectLink(j),k.id&&S.collectAnchor(k.id),D?(0,d.jsx)("a",{ref:E,href:j,...C&&!T&&{target:"_blank",rel:"noopener noreferrer"},...k}):(0,d.jsx)(P,{...k,onMouseEnter:I,onTouchStart:I,innerRef:e=>{E.current=e,O&&e&&T&&(R.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(R.current.unobserve(e),R.current.disconnect(),null!=j&&window.docusaurus.prefetch(j))}))})),R.current.observe(e))},to:j,...f&&{isActive:b,activeClassName:g}})}const f=r.forwardRef(p)},4357:(e,t,n)=>{"use strict";n.d(t,{c:()=>l,G:()=>c});var r=n(1504),o=n(7624);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=null==t?void 0:t[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(144);function s(e){var t,n;let{id:r,message:o}=e;if(void 0===r&&void 0===o)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return null!=(t=null!=(n=i[null!=r?r:o])?n:o)?t:r}function c(e,t){let{message:n,id:r}=e;return a(s({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},2488:(e,t,n)=>{"use strict";n.d(t,{M:()=>r});const r="default"},8136:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{_:()=>r,c:()=>o})},964:(e,t,n)=>{"use strict";n.d(t,{E:()=>i,c:()=>s});var r=n(1504),o=n(8264),a=n(8136);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,o.c)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a._)(n))return n;if(o)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},5976:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504);n(7624);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},8264:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(136);function a(){return(0,r.useContext)(o.e)}},3664:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(240);function a(){return(0,r.useContext)(o.e)}},5288:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(1504);const o=n(8684).c.canUseDOM?r.useLayoutEffect:r.useEffect},8120:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const s=o?o+"."+a:a;r(i)?e(i,s):t[s]=i}))}(e),t}},5548:(e,t,n)=>{"use strict";n.d(t,{Y:()=>i,e:()=>a});var r=n(1504),o=n(7624);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),s=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...null==n?void 0:n.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:s,children:t})}},2840:(e,t,n)=>{"use strict";n.d(t,{wB:()=>b,UF:()=>f,mU:()=>h,L0:()=>d,i8:()=>y,OK:()=>p,aA:()=>g,gN:()=>m});var r=n(5592),o=n(8264),a=n(2488);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.c)();return e}()[e];if(!n&&t.failfast)throw new Error('Docusaurus plugin global data not found for "'+e+'" plugin.');return n}const s=e=>e.versions.find((e=>e.isLast));function c(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.ot)(t,{path:e.path,exact:!1,strict:!1})))}function l(e,t){const n=c(e,t),o=null==n?void 0:n.docs.find((e=>!!(0,r.ot)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const u={},d=()=>{var e;return null!=(e=i("docusaurus-plugin-content-docs"))?e:u},p=e=>function(e,t,n){void 0===t&&(t=a.M),void 0===n&&(n={});const r=i(e),o=null==r?void 0:r[t];if(!o&&n.failfast)throw new Error('Docusaurus plugin global data not found for "'+e+'" plugin with id "'+t+'".');return o}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.IT)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.ot)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error("Can't find active docs plugin for \""+t+'" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: '+Object.values(e).map((e=>e.path)).join(", "));return a}(t,n,e)}function h(e){void 0===e&&(e={});const t=f(e),{pathname:n}=(0,r.IT)();if(!t)return;return{activePlugin:t,activeVersion:c(t.pluginData,n)}}function m(e){return p(e).versions}function g(e){const t=p(e);return s(t)}function b(e){const t=p(e),{pathname:n}=(0,r.IT)();return l(t,n)}function y(e){const t=p(e),{pathname:n}=(0,r.IT)();return function(e,t){const n=s(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},7483:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},1976:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(2272),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},5396:(e,t,n)=>{"use strict";n.r(t);var r=n(5720),o=n(7768);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(1808),n(2812)("./prism-"+e)})),delete globalThis.Prism}(r.sp)},6448:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(5456),o=n(4357),a=n(1824),i=n(867),s=n(5976);const c={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var l=n(7624);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.c)(),{navbar:{hideOnScroll:p}}=(0,a.y)();if("h1"===t||!n)return(0,l.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.G)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,l.jsxs)(t,{...u,className:(0,r.c)("anchor",p?c.anchorWithHideOnScrollNavbar:c.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,l.jsx)(i.c,{className:"hash-link",to:"#"+n,"aria-label":f,title:f,children:"\u200b"})]})}},3232:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(7624);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},7468:(e,t,n)=>{"use strict";n.d(t,{c:()=>Pt});var r=n(1504),o=n(5456),a=n(5852),i=n(5008),s=n(5592),c=n(4357),l=n(7124),u=n(7624);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.Uz)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=null!=(n=document.querySelector("main:first-of-type"))?n:document.getElementById(d);var n;t&&p(t)}),[]);return(0,l.c)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const h=(0,c.G)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function m(e){var t;const n=null!=(t=e.children)?t:h,{containerRef:r,onClick:o}=f();return(0,u.jsx)("div",{ref:r,role:"region","aria-label":h,children:(0,u.jsx)("a",{...e,href:"#"+d,onClick:o,children:n})})}var g=n(5864),b=n(204);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(m,{className:y.skipToContent})}var k=n(1824),x=n(3868);function w(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const _={closeButton:"closeButton_CVFx"};function S(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,c.G)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.c)("clean-btn close",_.closeButton,e.className),children:(0,u.jsx)(w,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,k.y)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.c)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function A(){const{announcementBar:e}=(0,k.y)(),{isActive:t,close:n}=(0,x.el)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:T.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:T.announcementBarPlaceholder}),(0,u.jsx)(C,{className:T.announcementBarContent}),a&&(0,u.jsx)(S,{onClick:n,className:T.announcementBarClose})]})}var j=n(8200),N=n(3943);var L=n(1100),P=n(5168);const O=r.createContext(null);function R(e){let{children:t}=e;const n=function(){const e=(0,j.q)(),t=(0,P.MF)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,L.i0)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(O.Provider,{value:n,children:t})}function I(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function M(){const e=(0,r.useContext)(O);if(!e)throw new L.AH("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,P.MF)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:I(a)})),[o,a,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=M();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.c)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var D=n(6528),z=n(3664);function B(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function U(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,z.c)(),s=(0,c.G)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,c.G)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.G)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.c)($.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.c)("clean-btn",$.toggleButton,!i&&$.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(B,{className:(0,o.c)($.toggleIcon,$.lightToggleIcon)}),(0,u.jsx)(U,{className:(0,o.c)($.toggleIcon,$.darkToggleIcon)})]})})}const V=r.memo(H),W={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function q(e){let{className:t}=e;const n=(0,k.y)().navbar.style,r=(0,k.y)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,D.U)();return r?null:(0,u.jsx)(V,{className:t,buttonClassName:"dark"===n?W.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(8164);function Y(){return(0,u.jsx)(G.c,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function K(){const e=(0,j.q)();return(0,u.jsx)("button",{type:"button","aria-label":(0,c.G)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(w,{color:"var(--ifm-color-emphasis-600)"})})}function Q(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(Y,{}),(0,u.jsx)(q,{className:"margin-right--md"}),(0,u.jsx)(K,{})]})}var Z=n(867),X=n(964),J=n(8136),ee=n(1064),te=n(3232);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:s,prependBaseUrlToHref:c,...l}=e;const d=(0,X.c)(r),p=(0,X.c)(t),f=(0,X.c)(o,{forcePrependBaseUrl:!0}),h=a&&o&&!(0,J.c)(o),m=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,h&&(0,u.jsx)(te.c,{...s&&{width:12,height:12}})]})};return o?(0,u.jsx)(Z.c,{href:c?f:o,...l,...m}):(0,u.jsx)(Z.c,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee._)(n,t.pathname):t.pathname.startsWith(p)},...l,...m})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.c)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.c)("menu__link",t),...r})})}function ae(e){var t;let{mobile:n=!1,position:r,...o}=e;const a=n?oe:re;return(0,u.jsx)(a,{...o,activeClassName:null!=(t=o.activeClassName)?t:n?"menu__link--active":"navbar__link--active"})}var ie=n(8448),se=n(3376),ce=n(8264);const le={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.Sc)(e.to,t)||!!(0,ee._)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){var t;let{items:n,position:a,className:i,onClick:s,...c}=e;const l=(0,r.useRef)(null),[d,p]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&p(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,o.c)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===a,"dropdown--show":d}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":d,role:"button",href:c.to?void 0:"#",className:(0,o.c)("navbar__link",i),...c,onClick:c.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),p(!d))},children:null!=(t=c.children)?t:c.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:n.map(((e,t)=>(0,r.createElement)(Ve,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){var t;let{items:n,className:a,position:i,onClick:c,...l}=e;const d=function(){const{siteConfig:{baseUrl:e}}=(0,ce.c)(),{pathname:t}=(0,s.IT)();return t.replace(e,"/")}(),p=ue(n,d),{collapsed:f,toggleCollapsed:h,setCollapsed:m}=(0,ie.a)({initialState:()=>!p});return(0,r.useEffect)((()=>{p&&m(!p)}),[d,p,m]),(0,u.jsxs)("li",{className:(0,o.c)("menu__list-item",{"menu__list-item--collapsed":f}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.c)(le.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",a),...l,onClick:e=>{e.preventDefault(),h()},children:null!=(t=l.children)?t:l.label}),(0,u.jsx)(ie.U,{lazy:!0,as:"ul",className:"menu__list",collapsed:f,children:n.map(((e,t)=>(0,r.createElement)(Ve,{mobile:!0,isDropdownItem:!0,onClick:c,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var he=n(1616);function me(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const ge="iconLanguage_nlXk";var be=n(7104);function ye(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var ve=n(5052),ke=["translations"];function xe(){return xe=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var Ee="Ctrl";var Ce=r.forwardRef((function(e,t){var n=e.translations,o=void 0===n?{}:n,a=Se(e,ke),i=o.buttonText,s=void 0===i?"Search":i,c=o.buttonAriaLabel,l=void 0===c?"Search":c,u=we((0,r.useState)(null),2),d=u[0],p=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?p("\u2318"):p(Ee))}),[]),r.createElement("button",xe({type:"button",className:"DocSearch DocSearch-Button","aria-label":l},a,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(ve.I,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===Ee?r.createElement(ye,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Te=n(6952),Ae=n(7092),je=n(9032),Ne=n(4456);const Le={button:{buttonText:(0,c.G)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.G)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.G)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.G)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.G)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.G)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.G)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.G)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.G)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.G)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.G)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.G)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.G)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.G)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.G)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.G)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.G)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.G)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.G)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.G)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.G)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.G)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.G)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.G)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.G)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.G)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.G)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Pe=null;function Oe(e){let{hit:t,children:n}=e;return(0,u.jsx)(Z.c,{to:t.url,children:n})}function Re(e){let{state:t,onClose:n}=e;const r=(0,Ae.Y)();return(0,u.jsx)(Z.c,{to:r(t.query),onClick:n,children:(0,u.jsx)(c.c,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Ie(e){var t,o;let{contextualSearch:a,externalUrlRegex:i,...c}=e;const{siteMetadata:l}=(0,ce.c)(),d=(0,je.Q)(),p=function(){const{locale:e,tags:t}=(0,Ne.mY)();return["language:"+e,t.map((e=>"docusaurus_tag:"+e))]}(),f=null!=(t=null==(o=c.searchParameters)?void 0:o.facetFilters)?t:[],h=a?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(p,f):f,m={...c.searchParameters,facetFilters:h},g=(0,s.Uz)(),b=(0,r.useRef)(null),y=(0,r.useRef)(null),[v,k]=(0,r.useState)(!1),[x,w]=(0,r.useState)(void 0),_=(0,r.useCallback)((()=>Pe?Promise.resolve():Promise.all([n.e(2528).then(n.bind(n,2528)),Promise.all([n.e(2176),n.e(1676)]).then(n.bind(n,1676)),Promise.all([n.e(2176),n.e(8879)]).then(n.bind(n,8879))]).then((e=>{let[{DocSearchModal:t}]=e;Pe=t}))),[]),S=(0,r.useCallback)((()=>{_().then((()=>{b.current=document.createElement("div"),document.body.insertBefore(b.current,document.body.firstChild),k(!0)}))}),[_,k]),E=(0,r.useCallback)((()=>{var e;k(!1),null==(e=b.current)||e.remove()}),[k]),C=(0,r.useCallback)((e=>{_().then((()=>{k(!0),w(e.key)}))}),[_,k,w]),T=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee._)(i,t)?window.location.href=t:g.push(t)}}).current,A=(0,r.useRef)((e=>c.transformItems?c.transformItems(e):e.map((e=>({...e,url:d(e.url)}))))).current,j=(0,r.useMemo)((()=>e=>(0,u.jsx)(Re,{...e,onClose:E})),[E]),N=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",l.docusaurusVersion),e)),[l.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,o=e.onClose,a=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;(27===e.keyCode&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?o():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&a&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&a(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,o,a,i])}({isOpen:v,onOpen:S,onClose:E,onInput:C,searchButtonRef:y}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Te.c,{children:(0,u.jsx)("link",{rel:"preconnect",href:"https://"+c.appId+"-dsn.algolia.net",crossOrigin:"anonymous"})}),(0,u.jsx)(Ce,{onTouchStart:_,onFocus:_,onMouseOver:_,onClick:S,ref:y,translations:Le.button}),v&&Pe&&b.current&&(0,be.createPortal)((0,u.jsx)(Pe,{onClose:E,initialScrollY:window.scrollY,initialQuery:x,navigator:T,transformItems:A,hitComponent:Oe,transformSearchClient:N,...c.searchPagePath&&{resultsFooterComponent:j},...c,searchParameters:m,placeholder:Le.placeholder,translations:Le.modal}),b.current)]})}function Me(){const{siteConfig:e}=(0,ce.c)();return(0,u.jsx)(Ie,{...e.themeConfig.algolia})}const Fe={navbarSearchContainer:"navbarSearchContainer_Bca1"};function De(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.c)(n,Fe.navbarSearchContainer),children:t})}var ze=n(2840),Be=n(9940);var Ue=n(4592);const $e=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:l,localeConfigs:d}}=(0,ce.c)(),p=(0,he.D)(),{search:f,hash:h}=(0,s.IT)(),m=[...n,...l.map((e=>{const n=""+("pathname://"+p.createUrl({locale:e,fullyQualified:!1}))+f+h+o;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,c.G)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(me,{className:ge}),g]}),items:m})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(De,{className:n,children:(0,u.jsx)(Me,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.c)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,ze.wB)(r),i=(0,Be.Qf)(t,r),s=(null==a?void 0:a.path)===(null==i?void 0:i.path);return null===i||i.unlisted&&!s?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>s||!(null==a||!a.sidebar)&&a.sidebar===i.sidebar,label:null!=n?n:i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,ze.wB)(r),i=(0,Be.Ab)(t,r).link;if(!i)throw new Error('DocSidebarNavbarItem: Sidebar with ID "'+t+"\" doesn't have anything to be linked to.");return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>(null==a?void 0:a.sidebar)===t,label:null!=n?n:i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Be.b7)(r)[0],i=null!=t?t:a.label,s=null!=n?n:(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:l,hash:d}=(0,s.IT)(),p=(0,ze.wB)(n),f=(0,ze.gN)(n),{savePreferredVersionName:h}=(0,Ue.iy)(n),m=[...o,...f.map((e=>{var t;const n=null!=(t=p.alternateDocVersions[e.name])?t:$e(e);return{label:e.label,to:""+n.path+l+d,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...a],g=(0,Be.b7)(n)[0],b=t&&m.length>1?(0,c.G)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,y=t&&m.length>1?void 0:$e(g).path;return m.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:y,items:m,isActive:r?()=>!1:void 0})}};function Ve(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=He[r];if(!o)throw new Error('No NavbarItem component found for type "'+t+'".');return(0,u.jsx)(o,{...n})}function We(){const e=(0,j.q)(),t=(0,k.y)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Ve,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function qe(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(c.c,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function Ge(){const e=0===(0,k.y)().navbar.items.length,t=M();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(qe,{onClick:()=>t.hide()}),t.content]})}function Ye(){const e=(0,j.q)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(F,{header:(0,u.jsx)(Q,{}),primaryMenu:(0,u.jsx)(We,{}),secondaryMenu:(0,u.jsx)(Ge,{})}):null}const Ke={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Qe(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.c)("navbar-sidebar__backdrop",e.className)})}function Ze(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,k.y)(),i=(0,j.q)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,N.SM)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+l{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,c.G)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.c)("navbar","navbar--fixed-top",n&&[Ke.navbarHideable,!d&&Ke.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Qe,{onClick:i.toggle}),(0,u.jsx)(Ye,{})]})}var Xe=n(5684);const Je={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function et(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(c.c,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function tt(e){let{error:t}=e;const n=(0,Xe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Je.errorBoundaryError,children:n})}class nt extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const rt="right";function ot(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function at(){const{toggle:e,shown:t}=(0,j.q)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,c.G)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(ot,{})})}const it={colorModeToggle:"colorModeToggle_DEke"};function st(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(nt,{onError:t=>new Error("A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n"+JSON.stringify(e,null,2),{cause:t}),children:(0,u.jsx)(Ve,{...e})},t)))})}function ct(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function lt(){const e=(0,j.q)(),t=(0,k.y)().navbar.items,[n,r]=function(e){function t(e){var t;return"left"===(null!=(t=e.position)?t:rt)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(ct,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(at,{}),(0,u.jsx)(Y,{}),(0,u.jsx)(st,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(st,{items:r}),(0,u.jsx)(q,{className:it.colorModeToggle}),!o&&(0,u.jsx)(De,{children:(0,u.jsx)(Me,{})})]})})}function ut(){return(0,u.jsx)(Ze,{children:(0,u.jsx)(lt,{})})}function dt(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,s=(0,X.c)(n),c=(0,X.c)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Z.c,{className:"footer__link-item",...r?{href:a?c:r}:{to:s},...i,children:[o,r&&!(0,J.c)(r)&&(0,u.jsx)(te.c,{})]})}function pt(e){var t;let{item:n}=e;return n.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:n.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(dt,{item:n})},null!=(t=n.href)?t:n.to)}function ft(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(pt,{item:e},t)))})]})}function ht(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(ft,{column:e},t)))})}function mt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function gt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(dt,{item:t})}function bt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(gt,{item:e}),t.length!==n+1&&(0,u.jsx)(mt,{})]},n)))})})}function yt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(ht,{columns:t}):(0,u.jsx)(bt,{links:t})}var vt=n(1964);const kt={footerLogoLink:"footerLogoLink_BH7S"};function xt(e){var t;let{logo:n}=e;const{withBaseUrl:r}=(0,X.E)(),a={light:r(n.src),dark:r(null!=(t=n.srcDark)?t:n.src)};return(0,u.jsx)(vt.c,{className:(0,o.c)("footer__logo",n.className),alt:n.alt,sources:a,width:n.width,height:n.height,style:n.style})}function wt(e){let{logo:t}=e;return t.href?(0,u.jsx)(Z.c,{href:t.href,className:kt.footerLogoLink,target:t.target,children:(0,u.jsx)(xt,{logo:t})}):(0,u.jsx)(xt,{logo:t})}function _t(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function St(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.c)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function Et(){const{footer:e}=(0,k.y)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(St,{style:o,links:n&&n.length>0&&(0,u.jsx)(yt,{links:n}),logo:r&&(0,u.jsx)(wt,{logo:r}),copyright:t&&(0,u.jsx)(_t,{copyright:t})})}const Ct=r.memo(Et),Tt=(0,L.qY)([D.C,x.qu,N.S2,Ue.gc,i.w7,function(e){let{children:t}=e;return(0,u.jsx)(P.Ub,{children:(0,u.jsx)(j.y,{children:(0,u.jsx)(R,{children:t})})})}]);function At(e){let{children:t}=e;return(0,u.jsx)(Tt,{children:t})}var jt=n(6448);function Nt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(jt.c,{as:"h1",className:"hero__title",children:(0,u.jsx)(c.c,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(et,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(tt,{error:t})})]})})})}const Lt={mainWrapper:"mainWrapper_z2l0"};function Pt(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:c}=e;return(0,b.W)(),(0,u.jsxs)(At,{children:[(0,u.jsx)(i.U7,{title:s,description:c}),(0,u.jsx)(v,{}),(0,u.jsx)(A,{}),(0,u.jsx)(ut,{}),(0,u.jsx)("div",{id:d,className:(0,o.c)(g.W.wrapper.main,Lt.mainWrapper,r),children:(0,u.jsx)(a.c,{fallback:e=>(0,u.jsx)(Nt,{...e}),children:t})}),!n&&(0,u.jsx)(Ct,{})]})}},8164:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(867),o=n(964),a=n(8264),i=n(1824),s=n(1964),c=n(7624);function l(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.c)(t.src),dark:(0,o.c)(t.srcDark||t.src)},i=(0,c.jsx)(s.c,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,c.jsx)("div",{className:r,children:i}):i}function u(e){var t;const{siteConfig:{title:n}}=(0,a.c)(),{navbar:{title:s,logo:u}}=(0,i.y)(),{imageClassName:d,titleClassName:p,...f}=e,h=(0,o.c)((null==u?void 0:u.href)||"/"),m=s?"":n,g=null!=(t=null==u?void 0:u.alt)?t:m;return(0,c.jsxs)(r.c,{to:h,...f,...(null==u?void 0:u.target)&&{target:u.target},children:[u&&(0,c.jsx)(l,{logo:u,alt:g,imageClassName:d}),null!=s&&(0,c.jsx)("b",{className:p,children:s})]})}},8712:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(6952),o=n(7624);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.c,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1964:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});var r=n(1504),o=n(5456),a=n(3664),i=n(6528);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var c=n(7624);function l(e){let{className:t,children:n}=e;const l=(0,a.c)(),{colorMode:u}=(0,i.U)();return(0,c.jsx)(c.Fragment,{children:(l?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.c)(t,s.themedComponent,s["themedComponent--"+e])});return(0,c.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,c.jsx)(l,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,c.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},8448:(e,t,n)=>{"use strict";n.d(t,{U:()=>b,a:()=>l});var r=n(1504),o=n(8684),a=n(5288),i=n(3856),s=n(7624);const c="ease-in-out";function l(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(null!=t&&t),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){var t,n;const r=e.scrollHeight,a=null!=(t=null==o?void 0:o.duration)?t:function(e){if((0,i.I)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(r);return{transition:"height "+a+"ms "+(null!=(n=null==o?void 0:o.easing)?n:c),height:r+"px"}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function h(e){if(!o.c.canUseDOM)return e?u:d}function m(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:c,disableSSRStyle:l}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,s.jsx)(t,{ref:u,style:l?void 0:h(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),null==i||i(n))},className:c,children:o})}function g(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[c,l]=(0,r.useState)(t);return(0,a.c)((()=>{t||i(!0)}),[t]),(0,a.c)((()=>{o&&l(t)}),[o,t]),o?(0,s.jsx)(m,{...n,collapsed:c}):null}function b(e){let{lazy:t,...n}=e;const r=t?g:m;return(0,s.jsx)(r,{...n})}},3868:(e,t,n)=>{"use strict";n.d(t,{el:()=>m,qu:()=>h});var r=n(1504),o=n(3664),a=n(1148),i=n(1100),s=n(1824),c=n(7624);const l=(0,a.GS)("docusaurus.announcement.dismiss"),u=(0,a.GS)("docusaurus.announcement.id"),d=()=>"true"===l.get(),p=e=>l.set(String(e)),f=r.createContext(null);function h(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.y)(),t=(0,o.c)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,c.jsx)(f.Provider,{value:n,children:t})}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.AH("AnnouncementBarProvider");return e}},6528:(e,t,n)=>{"use strict";n.d(t,{C:()=>g,U:()=>b});var r=n(1504),o=n(8684),a=n(1100),i=n(1148),s=n(1824),c=n(7624);const l=r.createContext(void 0),u="theme",d=(0,i.GS)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,h=e=>o.c.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.y)(),[o,a]=(0,r.useState)(h(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&m(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const c=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||c.current?c.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,c.jsx)(l.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(l);if(null==e)throw new a.AH("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},4592:(e,t,n)=>{"use strict";n.d(t,{eM:()=>k,gc:()=>b,iy:()=>v});var r=n(1504),o=n(2840),a=n(2488),i=n(1824),s=n(9940),c=n(1100),l=n(1148),u=n(7624);const d=e=>"docs-preferred-version-"+e,p={save:(e,t,n)=>{(0,l.GS)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,l.GS)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,l.GS)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const h=r.createContext(null);function m(){const e=(0,o.L0)(),t=(0,i.y)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,u.jsx)(h.Provider,{value:n,children:t})}function b(e){let{children:t}=e;return s.c1?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function y(){const e=(0,r.useContext)(h);if(!e)throw new c.AH("DocsPreferredVersionContextProvider");return e}function v(e){var t;void 0===e&&(e=a.M);const n=(0,o.OK)(e),[i,s]=y(),{preferredVersionName:c}=i[e];return{preferredVersion:null!=(t=n.versions.find((e=>e.name===c)))?t:null,savePreferredVersionName:(0,r.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}function k(){const e=(0,o.L0)(),[t]=y();function n(n){var r;const o=e[n],{preferredVersionName:a}=t[n];return null!=(r=o.versions.find((e=>e.name===a)))?r:null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},6192:(e,t,n)=>{"use strict";n.d(t,{m:()=>l,y:()=>c});var r=n(1504),o=n(1100),a=n(7624);const i=Symbol("EmptyContext"),s=r.createContext(i);function c(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(s.Provider,{value:i,children:t})}function l(){const e=(0,r.useContext)(s);if(e===i)throw new o.AH("DocsSidebarProvider");return e}},9920:(e,t,n)=>{"use strict";n.d(t,{E:()=>c,Q:()=>s});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(i);if(null===e)throw new o.AH("DocsVersionProvider");return e}},8200:(e,t,n)=>{"use strict";n.d(t,{q:()=>f,y:()=>p});var r=n(1504),o=n(5168),a=n(1432),i=n(632),s=n(1824),c=n(1100),l=n(7624);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.MF)(),{items:t}=(0,s.y)().navbar;return 0===t.length&&!e.component}(),t=(0,a.U)(),n=!e&&"mobile"===t,[c,l]=(0,r.useState)(!1);(0,i.a4)((()=>{if(c)return l(!1),!1}));const u=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:c})),[e,n,u,c])}function p(e){let{children:t}=e;const n=d();return(0,l.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new c.AH("NavbarMobileSidebarProvider");return e}},5168:(e,t,n)=>{"use strict";n.d(t,{MF:()=>c,Mx:()=>l,Ub:()=>s});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(i);if(!e)throw new o.AH("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.AH("NavbarSecondaryMenuContentProvider");const[,s]=a,c=(0,o.Mh)(n);return(0,r.useEffect)((()=>{s({component:t,props:c})}),[s,t,c]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},204:(e,t,n)=>{"use strict";n.d(t,{m:()=>o,W:()=>a});var r=n(1504);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7092:(e,t,n)=>{"use strict";n.d(t,{Y:()=>c,a:()=>s});var r=n(1504),o=n(8264),a=n(632);const i="q";function s(){return(0,a.E9)(i)}function c(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,o.c)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>""+e+n+"?"+i+"="+encodeURIComponent(t)),[e,n])}},1432:(e,t,n)=>{"use strict";n.d(t,{U:()=>s});var r=n(1504),o=n(8684);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!o.c.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},5864:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>"theme-admonition-"+e},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>"theme-doc-sidebar-item-category-level-"+e,docSidebarItemLinkLevel:e=>"theme-doc-sidebar-item-link-level-"+e},blog:{}}},3856:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{I:()=>r})},9940:(e,t,n)=>{"use strict";n.d(t,{Gw:()=>f,Md:()=>g,c1:()=>p,Uj:()=>S,b7:()=>x,Qf:()=>_,Ab:()=>w,js:()=>k,mg:()=>y});var r=n(1504),o=n(5592),a=n(5464),i=n(2840),s=n(4592),c=n(9920),l=n(6192);function u(e){return Array.from(new Set(e))}var d=n(3376);const p=!!i.L0;function f(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=f(t);if(e)return e}}(e):void 0:e.href}const h=(e,t)=>void 0!==e&&(0,d.Sc)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?h(e.href,t):"category"===e.type&&(h(e.href,t)||m(e.items,t))}function b(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>b(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function y(e,t){return(0,r.useMemo)((()=>e.filter((e=>b(e,t)))),[e,t])}function v(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.Sc)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.Sc)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function k(){var e;const t=(0,l.m)(),{pathname:n}=(0,o.IT)();return!1!==(null==(e=(0,i.UF)())?void 0:e.pluginData.breadcrumbs)&&t?v({sidebarItems:t.items,pathname:n}):null}function x(e){const{activeVersion:t}=(0,i.wB)(e),{preferredVersion:n}=(0,s.iy)(e),o=(0,i.aA)(e);return(0,r.useMemo)((()=>u([t,n,o].filter(Boolean))),[t,n,o])}function w(e,t){const n=x(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error("Can't find any sidebar with id \""+e+'" in version'+(n.length>1?"s":"")+" "+n.map((e=>e.name)).join(", ")+'".\nAvailable sidebar ids are:\n- '+t.map((e=>e[0])).join("\n- "));return r[1]}),[e,n])}function _(e,t){const n=x(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error("Couldn't find any doc with id \""+e+'" in version'+(n.length>1?"s":"")+' "'+n.map((e=>e.name)).join(", ")+'".\nAvailable doc ids are:\n- '+u(t.map((e=>e.id))).join("\n- "))}return r}),[e,n])}function S(e){let{route:t}=e;const n=(0,o.IT)(),r=(0,c.E)(),i=t.routes,s=i.find((e=>(0,o.ot)(n.pathname,e)));if(!s)return null;const l=s.sidebar,u=l?r.docsSidebars[l]:void 0;return{docElement:(0,a.k)(i),sidebarName:l,sidebarItems:u}}},8648:(e,t,n)=>{"use strict";n.d(t,{g:()=>o});var r=n(8264);function o(e){const{siteConfig:t}=(0,r.c)(),{title:n,titleDelimiter:o}=t;return null!=e&&e.trim().length?e.trim()+" "+o+" "+n:n}},632:(e,t,n)=>{"use strict";n.d(t,{E9:()=>c,a4:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){!function(e){const t=(0,o.Uz)(),n=(0,a.yA)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){return function(e){const t=(0,o.Uz)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function c(e){var t;const n=null!=(t=s(e))?t:"",a=function(){const e=(0,o.Uz)();return(0,r.useCallback)(((t,n,r)=>{const o=new URLSearchParams(e.location.search);n?o.set(t,n):o.delete(t),(null!=r&&r.push?e.push:e.replace)({search:o.toString()})}),[e])}();return[n,(0,r.useCallback)(((t,n)=>{a(e,t,n)}),[a,e])]}},5008:(e,t,n)=>{"use strict";n.d(t,{cr:()=>f,U7:()=>d,w7:()=>h});var r=n(1504),o=n(5456),a=n(6952),i=n(5548);function s(){const e=r.useContext(i.e);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var c=n(964),l=n(8648),u=n(7624);function d(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const s=(0,l.g)(t),{withBaseUrl:d}=(0,c.E)(),p=o?d(o,{absolute:!0}):void 0;return(0,u.jsxs)(a.c,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(p),s=(0,o.c)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(a.c,{children:(0,u.jsx)("html",{className:s})}),n]})}function h(e){let{children:t}=e;const n=s(),r="plugin-"+n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"");const a="plugin-id-"+n.plugin.id;return(0,u.jsx)(f,{className:(0,o.c)(r,a),children:t})}},1100:(e,t,n)=>{"use strict";n.d(t,{AH:()=>c,Mh:()=>l,i0:()=>s,qY:()=>u,yA:()=>i});var r=n(1504),o=n(5288),a=n(7624);function i(e){const t=(0,r.useRef)(e);return(0,o.c)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,o.c)((()=>{t.current=e})),t.current}class c extends Error{constructor(e,t){var n,r;super(),this.name="ReactContextError",this.message="Hook "+(null!=(n=null==(r=this.stack)||null==(r=r.split("\n")[1])||null==(r=r.match(/at (?:\w+\.)?(?\w+)/))?void 0:r.groups.name)?n:"")+" is called outside the <"+e+">. "+(null!=t?t:"")}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},1064:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{_:()=>r})},3376:(e,t,n)=>{"use strict";n.d(t,{Sc:()=>i,Y5:()=>s});var r=n(1504),o=n(628),a=n(8264);function i(e,t){const n=e=>{var t;return null==(t=!e||e.endsWith("/")?e:e+"/")?void 0:t.toLowerCase()};return n(e)===n(t)}function s(){const{baseUrl:e}=(0,a.c)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>{var t;return null!=(t=e.routes)?t:[]})))}(n)}({routes:o.c,baseUrl:e})),[e])}},3943:(e,t,n)=>{"use strict";n.d(t,{S2:()=>l,SM:()=>p,yI:()=>f});var r=n(1504),o=n(8684),a=n(3664),i=(n(5288),n(1100)),s=n(7624);const c=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(c.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(c);if(null==e)throw new i.AH("ScrollControllerProvider");return e}const d=()=>o.c.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),o=(0,r.useRef)(d()),a=(0,i.yA)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,a.c)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>null==e.current?void 0:e.current()}}},4456:(e,t,n)=>{"use strict";n.d(t,{SE:()=>s,e6:()=>i,mY:()=>c});var r=n(2840),o=n(8264),a=n(4592);const i="default";function s(e,t){return"docs-"+e+"-"+t}function c(){const{i18n:e}=(0,o.c)(),t=(0,r.L0)(),n=(0,r.mU)(),c=(0,a.eM)();const l=[i,...Object.keys(t).map((function(e){var r;const o=(null==n?void 0:n.activePlugin.pluginId)===e?n.activeVersion:void 0,a=c[e],i=t[e].versions.find((e=>e.isLast));return s(e,(null!=(r=null!=o?o:a)?r:i).name)}))];return{locale:e.currentLocale,tags:l}}},1148:(e,t,n)=>{"use strict";n.d(t,{GS:()=>c});n(1504);const r="localStorage";function o(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function a(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,i||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),i=!0),null}var t}let i=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error('Illegal storage API usage for storage key "'+e+'".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.')}return{get:t,set:t,del:t,listen:t}}(e);const n=a(null==t?void 0:t.persistence);return null===n?s:{get:()=>{try{return n.getItem(e)}catch(t){return console.error("Docusaurus storage error, can't get key="+e,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),o({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error("Docusaurus storage error, can't set "+e+"="+t,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),o({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error("Docusaurus storage error, can't delete key="+e,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error("Docusaurus storage error, can't listen for changes of key="+e,r),()=>{}}}}}},1616:(e,t,n)=>{"use strict";n.d(t,{D:()=>i});var r=n(8264),o=n(5592),a=n(5684);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.c)(),{pathname:c}=(0,o.IT)(),l=(0,a.applyTrailingSlash)(c,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace("/"+s+"/","/"),d=l.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return""+(r?t:"")+function(e){return e===i?""+u:""+u+e+"/"}(n)+d}}}},7124:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){const t=(0,o.IT)(),n=(0,a.i0)(t),i=(0,a.yA)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},1824:(e,t,n)=>{"use strict";n.d(t,{y:()=>o});var r=n(8264);function o(){return(0,r.c)().siteConfig.themeConfig}},8589:(e,t,n)=>{"use strict";n.d(t,{E:()=>o});var r=n(8264);function o(){const{siteConfig:{themeConfig:e}}=(0,r.c)();return e}},9032:(e,t,n)=>{"use strict";n.d(t,{Q:()=>s});var r=n(1504),o=n(1064),a=n(964),i=n(8589);function s(){const{withBaseUrl:e}=(0,a.E)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.E)();return(0,r.useCallback)((r=>{const a=new URL(r);if((0,o._)(t,a.href))return r;const i=""+(a.pathname+a.hash);return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},1600:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[o]=e.split(/[#?]/),a="/"===o||o===r?o:(i=o,n?function(e){return e.endsWith("/")?e:e+"/"}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(o,a)}},4292:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},5684:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(1600);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}});var a=n(4292);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return a.getErrorCausalChain}})},8064:(e,t,n)=>{"use strict";n.d(t,{iU:()=>k,Yf:()=>C,gh:()=>f,Wi:()=>A,Ep:()=>p});var r=n(5072);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!l)for(;d--;d)i.unshift("..");!l||""===i[0]||i[0]&&o(i[0])||i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};var s=n(4812);function c(e){return"/"===e.charAt(0)?e:"/"+e}function l(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.c)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function h(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,m(),k.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(k.entries[k.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=k.index+e;return t>=0&&t{"use strict";var r=n(2168),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function c(e){return r.isMemo(e)?i:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var l=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=f(n);o&&o!==h&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=c(t),m=c(n),g=0;g{"use strict";e.exports=function(e,t,n,r,o,a,i,s){if(!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,a,i,s],u=0;(c=new Error(t.replace(/%s/g,(function(){return l[u++]})))).name="Invariant Violation"}throw c.framesToPop=1,c}}},9600:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},1462:(e,t,n)=>{"use strict";n.r(t)},1496:(e,t,n)=>{"use strict";n.r(t)},2272:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),l=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),c(l,i(e,u,d)),1===e?(c(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){c(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),s=e?"-100":a(n.status||0),l=document.querySelector(r.parent);return c(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),c=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function l(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);l(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},7184:()=>{!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,r={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[r,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:r.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:r.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":r,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:r.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:r.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},1808:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,s=i.length;-1!==n.code.indexOf(o=t(r,s));)++s;return i[s]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(s){for(var c=0;c=a.length);c++){var l=s[c];if("string"==typeof l||l.content&&"string"==typeof l.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof l?l:l.content,f=t(r,u),h=p.indexOf(f);if(h>-1){++o;var m=p.substring(0,h),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(h+f.length),y=[];m&&y.push.apply(y,i([m])),y.push(g),b&&y.push.apply(y,i([b])),"string"==typeof l?s.splice.apply(s,[c,1].concat(y)):l.content=y}}else l.content&&i(l.content)}return s}(n.tokens)}}}})}(Prism)},2812:(e,t,n)=>{var r={"./prism-java":7184};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=2812},9776:(e,t,n)=>{"use strict";var r=n(9143);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},3268:(e,t,n)=>{e.exports=n(9776)()},9143:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},9516:(e,t,n)=>{"use strict";var r=n(1504),o=n(4712);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n