From 7fcc88654fa81ba6bd511f62ef6b0223f90d7fae Mon Sep 17 00:00:00 2001
From: facebook-github-bot
Date: Thu, 19 Dec 2024 14:01:10 +0000
Subject: [PATCH] Deploy website - based on
6ce07689df2023419f2ed8f0fd44fab6bc007aa7
---
404.html | 2 +-
...e4035.b69a3096.js => 041e4035.e204036c.js} | 2 +-
assets/js/223037ba.2aa7902c.js | 1 -
assets/js/223037ba.890494e4.js | 1 +
...eae25.904d52c1.js => 8fdeae25.5a49904a.js} | 2 +-
assets/js/c359af60.1278ce61.js | 1 -
assets/js/c359af60.87765c92.js | 1 +
...n.bf22b583.js => runtime~main.f2ef44c5.js} | 2 +-
.../index.html | 2 +-
.../17/collaboration-with-spotify/index.html | 2 +-
.../07/mobileatscale-london-talk/index.html | 2 +-
.../06/23/first-opensourceversary/index.html | 2 +-
blog/2016/08/30/curryon-rome-talk/index.html | 2 +-
blog/2016/11/28/atscale16/index.html | 2 +-
.../10/20/ocamlformat-released/index.html | 2 +-
blog/archive/index.html | 2 +-
blog/index.html | 2 +-
docs/1.1.0/about-Infer/index.html | 2 +-
docs/1.1.0/absint-framework/index.html | 2 +-
docs/1.1.0/all-issue-types/index.html | 2 +-
.../analyzing-apps-or-projects/index.html | 2 +-
.../index.html | 2 +-
docs/1.1.0/checker-biabduction/index.html | 2 +-
docs/1.1.0/checker-bufferoverrun/index.html | 2 +-
.../index.html | 2 +-
.../checker-config-impact-analysis/index.html | 2 +-
docs/1.1.0/checker-cost/index.html | 2 +-
.../checker-dotnet-resource-leak/index.html | 2 +-
docs/1.1.0/checker-eradicate/index.html | 2 +-
.../checker-fragment-retains-view/index.html | 2 +-
docs/1.1.0/checker-immutable-cast/index.html | 2 +-
docs/1.1.0/checker-impurity/index.html | 2 +-
.../index.html | 2 +-
docs/1.1.0/checker-linters/index.html | 2 +-
.../checker-litho-required-props/index.html | 2 +-
docs/1.1.0/checker-liveness/index.html | 2 +-
docs/1.1.0/checker-loop-hoisting/index.html | 2 +-
docs/1.1.0/checker-printf-args/index.html | 2 +-
docs/1.1.0/checker-pulse/index.html | 2 +-
docs/1.1.0/checker-purity/index.html | 2 +-
docs/1.1.0/checker-quandary/index.html | 2 +-
docs/1.1.0/checker-racerd/index.html | 2 +-
.../checker-resource-leak-lab/index.html | 2 +-
docs/1.1.0/checker-self-in-block/index.html | 2 +-
docs/1.1.0/checker-siof/index.html | 2 +-
docs/1.1.0/checker-starvation/index.html | 2 +-
docs/1.1.0/checker-topl/index.html | 2 +-
docs/1.1.0/checker-uninit/index.html | 2 +-
docs/1.1.0/getting-started/index.html | 2 +-
docs/1.1.0/hello-world/index.html | 2 +-
docs/1.1.0/infer-workflow/index.html | 2 +-
docs/1.1.0/internal-API/index.html | 2 +-
docs/1.1.0/man-infer-analyze/index.html | 2 +-
docs/1.1.0/man-infer-capture/index.html | 2 +-
docs/1.1.0/man-infer-compile/index.html | 2 +-
docs/1.1.0/man-infer-debug/index.html | 2 +-
docs/1.1.0/man-infer-explore/index.html | 2 +-
docs/1.1.0/man-infer-help/index.html | 2 +-
docs/1.1.0/man-infer-report/index.html | 2 +-
docs/1.1.0/man-infer-reportdiff/index.html | 2 +-
docs/1.1.0/man-infer-run/index.html | 2 +-
docs/1.1.0/man-infer/index.html | 2 +-
docs/1.1.0/man-pages/index.html | 2 +-
.../index.html | 2 +-
docs/1.1.0/steps-for-ci/index.html | 2 +-
docs/1.1.0/support/index.html | 2 +-
docs/1.1.0/versions/index.html | 2 +-
docs/about-Infer/index.html | 2 +-
docs/absint-framework/index.html | 2 +-
docs/all-categories/index.html | 2 +-
docs/all-checkers/index.html | 2 +-
docs/all-issue-types/index.html | 2 +-
docs/analyzing-apps-or-projects/index.html | 2 +-
.../index.html | 2 +-
docs/checker-biabduction/index.html | 2 +-
docs/checker-bufferoverrun/index.html | 2 +-
.../checker-config-impact-analysis/index.html | 2 +-
docs/checker-cost/index.html | 2 +-
docs/checker-datalog/index.html | 2 +-
docs/checker-fragment-retains-view/index.html | 2 +-
docs/checker-impurity/index.html | 2 +-
.../index.html | 2 +-
docs/checker-lineage/index.html | 2 +-
docs/checker-litho-required-props/index.html | 2 +-
docs/checker-liveness/index.html | 2 +-
docs/checker-loop-hoisting/index.html | 2 +-
.../index.html | 2 +-
docs/checker-printf-args/index.html | 2 +-
docs/checker-pulse/index.html | 2 +-
docs/checker-purity/index.html | 2 +-
docs/checker-quandary/index.html | 2 +-
docs/checker-racerd/index.html | 2 +-
docs/checker-resource-leak-lab/index.html | 2 +-
docs/checker-scope-leakage/index.html | 2 +-
docs/checker-self-in-block/index.html | 2 +-
docs/checker-sil-validation/index.html | 2 +-
docs/checker-siof/index.html | 2 +-
docs/checker-starvation/index.html | 2 +-
docs/checker-topl/index.html | 2 +-
docs/getting-started/index.html | 2 +-
docs/hello-world/index.html | 2 +-
docs/infer-workflow/index.html | 2 +-
docs/internal-API/index.html | 2 +-
docs/man-infer-analyze/index.html | 2 +-
docs/man-infer-capture/index.html | 2 +-
docs/man-infer-compile/index.html | 2 +-
docs/man-infer-debug/index.html | 2 +-
docs/man-infer-explore/index.html | 2 +-
docs/man-infer-help/index.html | 2 +-
docs/man-infer-report/index.html | 2 +-
docs/man-infer-reportdiff/index.html | 2 +-
docs/man-infer-run/index.html | 2 +-
docs/man-infer/index.html | 2 +-
docs/man-pages/index.html | 2 +-
docs/next/about-Infer/index.html | 2 +-
docs/next/absint-framework/index.html | 2 +-
docs/next/all-categories/index.html | 4 +-
docs/next/all-checkers/index.html | 2 +-
docs/next/all-issue-types/index.html | 12 +-
.../analyzing-apps-or-projects/index.html | 2 +-
.../index.html | 2 +-
docs/next/checker-biabduction/index.html | 2 +-
docs/next/checker-bufferoverrun/index.html | 2 +-
.../checker-config-impact-analysis/index.html | 2 +-
docs/next/checker-cost/index.html | 2 +-
.../checker-fragment-retains-view/index.html | 2 +-
docs/next/checker-impurity/index.html | 2 +-
.../index.html | 2 +-
docs/next/checker-lineage/index.html | 2 +-
.../checker-litho-required-props/index.html | 2 +-
docs/next/checker-liveness/index.html | 2 +-
docs/next/checker-loop-hoisting/index.html | 2 +-
.../index.html | 2 +-
docs/next/checker-pulse/index.html | 3 +-
docs/next/checker-purity/index.html | 2 +-
docs/next/checker-racerd/index.html | 2 +-
.../next/checker-resource-leak-lab/index.html | 2 +-
docs/next/checker-scope-leakage/index.html | 2 +-
docs/next/checker-self-in-block/index.html | 2 +-
docs/next/checker-sil-validation/index.html | 2 +-
docs/next/checker-siof/index.html | 2 +-
docs/next/checker-starvation/index.html | 3 +-
.../index.html | 2 +-
docs/next/checker-topl/index.html | 2 +-
docs/next/getting-started/index.html | 2 +-
docs/next/hello-world/index.html | 2 +-
docs/next/infer-workflow/index.html | 2 +-
docs/next/internal-API/index.html | 2 +-
docs/next/man-infer-analyze/index.html | 2 +-
docs/next/man-infer-capture/index.html | 2 +-
docs/next/man-infer-compile/index.html | 2 +-
docs/next/man-infer-debug/index.html | 2 +-
docs/next/man-infer-explore/index.html | 2 +-
docs/next/man-infer-help/index.html | 2 +-
docs/next/man-infer-report/index.html | 2 +-
docs/next/man-infer-reportdiff/index.html | 2 +-
docs/next/man-infer-run/index.html | 2 +-
docs/next/man-infer/index.html | 2 +-
docs/next/man-pages/index.html | 2 +-
.../index.html | 2 +-
docs/next/steps-for-ci/index.html | 2 +-
docs/next/support/index.html | 2 +-
docs/next/suppressions/index.html | 2 +-
docs/next/versions/index.html | 2 +-
.../index.html | 2 +-
docs/steps-for-ci/index.html | 2 +-
docs/support/index.html | 2 +-
docs/versions/index.html | 2 +-
index.html | 2 +-
man/next/infer-analyze.1.html | 854 +++++----
man/next/infer-capture.1.html | 383 ++--
man/next/infer-compile.1.html | 77 +-
man/next/infer-debug.1.html | 140 +-
man/next/infer-explore.1.html | 54 +-
man/next/infer-help.1.html | 62 +-
man/next/infer-report.1.html | 208 ++-
man/next/infer-reportdiff.1.html | 103 +-
man/next/infer-run.1.html | 197 ++-
man/next/infer.1.html | 1542 ++++++++---------
.../Absint/AbstractDomain/NodeSet/index.html | 6 +
.../module-type-NodeSetS/index.html | 6 +
.../Absint/RecursiveCycleException/index.html | 2 +
odoc/next/infer/Backend/GCStats/index.html | 2 +-
odoc/next/infer/Backend/Ondemand/index.html | 2 +-
.../Mem/index.html | 2 +
.../Summary/index.html | 2 +
.../StaticConstructorStallChecker/index.html | 2 +
.../ClangFrontend/CTrans_utils/index.html | 2 +-
.../StarvationDomain/ThreadDomain/index.html | 2 +-
.../infer/IBase/AnalysisRequest/index.html | 2 +-
odoc/next/infer/IBase/Config/index.html | 8 +-
.../infer/IBase/EarlyScubaLogging/index.html | 2 -
.../infer/IBase/ExecutionDuration/index.html | 2 +-
odoc/next/infer/IBase/IssueType/index.html | 2 +-
odoc/next/infer/IBase/Language/index.html | 2 +-
odoc/next/infer/IBase/LogEntry/index.html | 2 +-
odoc/next/infer/IBase/Process/index.html | 8 +-
odoc/next/infer/IBase/Scuba/index.html | 2 -
odoc/next/infer/IBase/SourceFile/index.html | 2 +-
odoc/next/infer/IBase/Stats/index.html | 2 +-
.../{ScubaLogging => StatsLogging}/index.html | 4 +-
odoc/next/infer/IBase/StatsSample/index.html | 2 +
odoc/next/infer/IBase/Timings/index.html | 2 +-
odoc/next/infer/IBase/ToplAst/index.html | 2 +-
odoc/next/infer/IBase/ToplLexer/index.html | 2 +-
odoc/next/infer/IBase/Utils/index.html | 4 +-
odoc/next/infer/IBase/index.html | 2 +-
.../infer/IR/AnalysisGlobalState/index.html | 7 +-
odoc/next/infer/IR/CallFlags/index.html | 2 +-
odoc/next/infer/IR/Dependencies/index.html | 2 +-
odoc/next/infer/IR/Fieldname/index.html | 2 +-
odoc/next/infer/IR/Io_infer/Html/index.html | 11 +-
odoc/next/infer/IR/ProcAttributes/index.html | 18 +-
odoc/next/infer/IR/Procdesc/Loop/index.html | 2 +
.../next/infer/IR/Procdesc/NodeSet/index.html | 2 +
odoc/next/infer/IR/Procname/index.html | 4 +-
odoc/next/infer/IR/PythonClassName/index.html | 2 +-
odoc/next/infer/IR/Typ/Name/index.html | 2 +-
odoc/next/infer/IStdlib/IStd/index.html | 2 +-
.../next/infer/IStdlib/IString/Map/index.html | 14 +
.../next/infer/IStdlib/IString/Set/index.html | 5 +
odoc/next/infer/IStdlib/IString/index.html | 2 +
.../MakeConcurrentMap/index.html | 2 +
.../infer/IStdlib/PrettyPrintable/index.html | 4 +-
.../module-type-ConcurrentMap/index.html | 2 +
.../CanonValue/Attributes/index.html | 6 +-
.../Pulselib/PulseAbductiveDomain/index.html | 13 +-
.../Pulselib/PulseAccessResult/index.html | 11 +-
.../PulseBaseAddressAttributes/index.html | 6 +-
.../module-type-S/index.html | 6 +-
.../Pulselib/PulseCallOperations/index.html | 4 +-
.../Make/Attributes/index.html | 6 +-
.../module-type-S/Attributes/index.html | 6 +-
.../infer/Pulselib/PulseDiagnostic/index.html | 4 +-
odoc/next/infer/Pulselib/PulseJoin/index.html | 8 +
.../Pulselib/PulseModelsDSL/Syntax/index.html | 12 +-
.../Pulselib/PulseModelsPython/index.html | 2 +
.../Pulselib/PulseMutualRecursion/index.html | 13 +-
.../Summary/index.html | 4 +-
.../PulseNonDisjunctiveDomain/index.html | 7 +-
.../infer/Pulselib/PulseOperations/index.html | 7 +-
.../Pulselib/PulsePathContext/index.html | 2 +-
.../infer/Pulselib/PulseReport/index.html | 4 +
.../infer/Pulselib/PulseResult/index.html | 7 +-
.../infer/Pulselib/PulseSummary/index.html | 5 +-
.../PulseTaintConfig/SinkPolicy/index.html | 2 +-
.../Pulselib/PulseTaintConfig/Unit/index.html | 2 +-
.../PythonFrontend/PyIR2Textual/index.html | 4 +
.../infer/Textuallib/TextualSil/index.html | 2 +-
.../Textuallib/TextualVerification/index.html | 8 +
search/index.html | 2 +-
251 files changed, 2196 insertions(+), 2090 deletions(-)
rename assets/js/{041e4035.b69a3096.js => 041e4035.e204036c.js} (71%)
delete mode 100644 assets/js/223037ba.2aa7902c.js
create mode 100644 assets/js/223037ba.890494e4.js
rename assets/js/{8fdeae25.904d52c1.js => 8fdeae25.5a49904a.js} (55%)
delete mode 100644 assets/js/c359af60.1278ce61.js
create mode 100644 assets/js/c359af60.87765c92.js
rename assets/js/{runtime~main.bf22b583.js => runtime~main.f2ef44c5.js} (97%)
create mode 100644 odoc/next/infer/Absint/AbstractDomain/NodeSet/index.html
create mode 100644 odoc/next/infer/Absint/AbstractDomain/module-type-NodeSetS/index.html
create mode 100644 odoc/next/infer/Absint/RecursiveCycleException/index.html
create mode 100644 odoc/next/infer/Checkers/StaticConstructorStallChecker/Mem/index.html
create mode 100644 odoc/next/infer/Checkers/StaticConstructorStallChecker/Summary/index.html
create mode 100644 odoc/next/infer/Checkers/StaticConstructorStallChecker/index.html
delete mode 100644 odoc/next/infer/IBase/EarlyScubaLogging/index.html
delete mode 100644 odoc/next/infer/IBase/Scuba/index.html
rename odoc/next/infer/IBase/{ScubaLogging => StatsLogging}/index.html (54%)
create mode 100644 odoc/next/infer/IBase/StatsSample/index.html
create mode 100644 odoc/next/infer/IR/Procdesc/Loop/index.html
create mode 100644 odoc/next/infer/IR/Procdesc/NodeSet/index.html
create mode 100644 odoc/next/infer/IStdlib/IString/Map/index.html
create mode 100644 odoc/next/infer/IStdlib/IString/Set/index.html
create mode 100644 odoc/next/infer/IStdlib/IString/index.html
create mode 100644 odoc/next/infer/IStdlib/PrettyPrintable/MakeConcurrentMap/index.html
create mode 100644 odoc/next/infer/IStdlib/PrettyPrintable/module-type-ConcurrentMap/index.html
create mode 100644 odoc/next/infer/Pulselib/PulseJoin/index.html
create mode 100644 odoc/next/infer/Pulselib/PulseModelsPython/index.html
create mode 100644 odoc/next/infer/PythonFrontend/PyIR2Textual/index.html
create mode 100644 odoc/next/infer/Textuallib/TextualVerification/index.html
diff --git a/404.html b/404.html
index 55275424a4a..fcf5fdbb1cf 100644
--- a/404.html
+++ b/404.html
@@ -13,7 +13,7 @@
-
+
diff --git a/assets/js/041e4035.b69a3096.js b/assets/js/041e4035.e204036c.js
similarity index 71%
rename from assets/js/041e4035.b69a3096.js
rename to assets/js/041e4035.e204036c.js
index 57a1bdc155b..f811e060f94 100644
--- a/assets/js/041e4035.b69a3096.js
+++ b/assets/js/041e4035.e204036c.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8045],{4364:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var i=s(4848),t=s(8453);const r={title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors."},o=void 0,c={id:"checker-starvation",title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors.",source:"@site/docs/checker-starvation.md",sourceDirName:".",slug:"/checker-starvation",permalink:"/docs/next/checker-starvation",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors."},sidebar:"docs",previous:{title:"Self in Block",permalink:"/docs/next/checker-self-in-block"},next:{title:"Topl",permalink:"/docs/next/checker-topl"}},l={},d=[{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function a(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Detect various kinds of situations when no progress is being made because of concurrency errors."}),"\n",(0,i.jsxs)(n.p,{children:["Activate with ",(0,i.jsx)(n.code,{children:"--starvation"}),"."]}),"\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.p,{children:'Detect several kinds of "starvation" problems:'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"deadlocks"}),"\n",(0,i.jsxs)(n.li,{children:["violations of ",(0,i.jsx)(n.code,{children:"@Lockless"})," annotations"]}),"\n",(0,i.jsxs)(n.li,{children:["violations of ",(0,i.jsx)(n.a,{href:"https://developer.android.com/reference/android/os/StrictMode",children:'Android\'s "strict mode"'})]}),"\n",(0,i.jsx)(n.li,{children:"doing expensive operations on the Android UI thread"}),"\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#arbitrary_code_execution_under_lock",children:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#deadlock",children:"DEADLOCK"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#lockless_violation",children:"LOCKLESS_VIOLATION"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#starvation",children:"STARVATION"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#strict_mode_violation",children:"STRICT_MODE_VIOLATION"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>c});var i=s(6540);const t={},r=i.createContext(t);function o(e){const n=i.useContext(r);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(t):e.components||t:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8045],{4364:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>c,toc:()=>d});var i=s(4848),r=s(8453);const t={title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors."},o=void 0,c={id:"checker-starvation",title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors.",source:"@site/docs/checker-starvation.md",sourceDirName:".",slug:"/checker-starvation",permalink:"/docs/next/checker-starvation",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Starvation",description:"Detect various kinds of situations when no progress is being made because of concurrency errors."},sidebar:"docs",previous:{title:"Self in Block",permalink:"/docs/next/checker-self-in-block"},next:{title:"Topl",permalink:"/docs/next/checker-topl"}},l={},d=[{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function a(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Detect various kinds of situations when no progress is being made because of concurrency errors."}),"\n",(0,i.jsxs)(n.p,{children:["Activate with ",(0,i.jsx)(n.code,{children:"--starvation"}),"."]}),"\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.p,{children:'Detect several kinds of "starvation" problems:'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"deadlocks"}),"\n",(0,i.jsxs)(n.li,{children:["violations of ",(0,i.jsx)(n.code,{children:"@Lockless"})," annotations"]}),"\n",(0,i.jsxs)(n.li,{children:["violations of ",(0,i.jsx)(n.a,{href:"https://developer.android.com/reference/android/os/StrictMode",children:'Android\'s "strict mode"'})]}),"\n",(0,i.jsx)(n.li,{children:"doing expensive operations on the Android UI thread"}),"\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#arbitrary_code_execution_under_lock",children:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#deadlock",children:"DEADLOCK"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#lockless_violation",children:"LOCKLESS_VIOLATION"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#lock_on_ui_thread",children:"LOCK_ON_UI_THREAD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#starvation",children:"STARVATION"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/next/all-issue-types#strict_mode_violation",children:"STRICT_MODE_VIOLATION"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>c});var i=s(6540);const r={},t=i.createContext(r);function o(e){const n=i.useContext(t);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:o(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/223037ba.2aa7902c.js b/assets/js/223037ba.2aa7902c.js
deleted file mode 100644
index c3978ef039c..00000000000
--- a/assets/js/223037ba.2aa7902c.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9383],{1483:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>_,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>a});var l=n(4848),i=n(8453);const r={title:"List of all categories of issue types"},t=void 0,c={id:"all-categories",title:"List of all categories of issue types",description:"Here are all the categories that issue types might belong to in Infer. Some issue types have no associated category at the moment. This usually indicates that the issue type is not yet mature enough to be used.",source:"@site/docs/all-categories.md",sourceDirName:".",slug:"/all-categories",permalink:"/docs/next/all-categories",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"List of all categories of issue types"},sidebar:"docs",previous:{title:"List of all checkers",permalink:"/docs/next/all-checkers"},next:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"}},_={},a=[{value:"Concurrency",id:"concurrency",level:2},{value:"Logic error",id:"logic-error",level:2},{value:"Memory error",id:"memory-error",level:2},{value:"Null pointer dereference",id:"null-pointer-dereference",level:2},{value:"Perf regression",id:"perf-regression",level:2},{value:"Resource leak",id:"resource-leak",level:2},{value:"Runtime exception",id:"runtime-exception",level:2},{value:"Sensitive data flow",id:"sensitive-data-flow",level:2},{value:"Ungated code",id:"ungated-code",level:2},{value:"User defined property",id:"user-defined-property",level:2}];function d(e){const s={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(s.p,{children:"Here are all the categories that issue types might belong to in Infer. Some issue types have no associated category at the moment. This usually indicates that the issue type is not yet mature enough to be used."}),"\n",(0,l.jsx)(s.h2,{id:"concurrency",children:"Concurrency"}),"\n",(0,l.jsx)(s.p,{children:"Concurrent accesses to the same resource conflict in a way that can give incorrect results, block progress, or result in undefined behaviour."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#deadlock",children:"DEADLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#guardedby_violation",children:"GUARDEDBY_VIOLATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#static_constructor_stall",children:"STATIC_CONSTRUCTOR_STALL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"logic-error",children:"Logic error"}),"\n",(0,l.jsx)(s.p,{children:"Something that does not make sense and the sign of a potential programming error."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#dead_store",children:"DEAD_STORE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"memory-error",children:"Memory error"}),"\n",(0,l.jsx)(s.p,{children:"Incorrect handling of pointers that isn't a null pointer dereference, but can still result in undefined behaviour and crashes."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#cxx_string_captured_in_block",children:"CXX_STRING_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nsstring_internal_ptr_captured_in_block",children:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"null-pointer-dereference",children:"Null pointer dereference"}),"\n",(0,l.jsx)(s.p,{children:"The null pointer is used where a valid pointer is required, causing a memory fault and a crash. For example, it is dereferenced."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_dereference",children:"NULL_DEREFERENCE"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"perf-regression",children:"Perf regression"}),"\n",(0,l.jsx)(s.p,{children:"Unnecessary (or blocking) computation is performed, potentially causing a performance or responsiveness regression."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#config_impact",children:"CONFIG_IMPACT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#strict_mode_violation",children:"STRICT_MODE_VIOLATION"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"resource-leak",children:"Resource leak"}),"\n",(0,l.jsx)(s.p,{children:"A resource (for example memory, or a file descriptor) has been manually allocated but not released, possibly creating memory pressure over time or even incorrect results."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#biabduction_memory_leak",children:"BIABDUCTION_MEMORY_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#biabduction_retain_cycle",children:"BIABDUCTION_RETAIN_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#captured_strong_self",children:"CAPTURED_STRONG_SELF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_fragment_retains_view",children:"CHECKERS_FRAGMENT_RETAINS_VIEW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#resource_leak",children:"RESOURCE_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#self_in_block_passed_to_init",children:"SELF_IN_BLOCK_PASSED_TO_INIT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"runtime-exception",children:"Runtime exception"}),"\n",(0,l.jsx)(s.p,{children:"A runtime exception can occur and potentially crash the program."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_generator",children:"BAD_GENERATOR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_generator_latent",children:"BAD_GENERATOR_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#missing_required_prop",children:"MISSING_REQUIRED_PROP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"sensitive-data-flow",children:"Sensitive data flow"}),"\n",(0,l.jsx)(s.p,{children:"Sensitive data is flowing where it shouldn't."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#lineage_flow",children:"LINEAGE_FLOW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#scope_leakage",children:"SCOPE_LEAKAGE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"ungated-code",children:"Ungated code"}),"\n",(0,l.jsx)(s.p,{children:"Code must be under a gating mechanism but isn't."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#config_impact_strict",children:"CONFIG_IMPACT_STRICT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"user-defined-property",children:"User defined property"}),"\n",(0,l.jsx)(s.p,{children:"A user defined (custom) property is violated."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#topl_error",children:"TOPL_ERROR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#topl_error_latent",children:"TOPL_ERROR_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,l.jsx)(s,{...e,children:(0,l.jsx)(d,{...e})}):d(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>t,x:()=>c});var l=n(6540);const i={},r=l.createContext(i);function t(e){const s=l.useContext(r);return l.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),l.createElement(r.Provider,{value:s},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/223037ba.890494e4.js b/assets/js/223037ba.890494e4.js
new file mode 100644
index 00000000000..30f3a1d1b09
--- /dev/null
+++ b/assets/js/223037ba.890494e4.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9383],{1483:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>_,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>a});var l=n(4848),i=n(8453);const r={title:"List of all categories of issue types"},t=void 0,c={id:"all-categories",title:"List of all categories of issue types",description:"Here are all the categories that issue types might belong to in Infer. Some issue types have no associated category at the moment. This usually indicates that the issue type is not yet mature enough to be used.",source:"@site/docs/all-categories.md",sourceDirName:".",slug:"/all-categories",permalink:"/docs/next/all-categories",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"List of all categories of issue types"},sidebar:"docs",previous:{title:"List of all checkers",permalink:"/docs/next/all-checkers"},next:{title:"List of all issue types",permalink:"/docs/next/all-issue-types"}},_={},a=[{value:"Concurrency",id:"concurrency",level:2},{value:"Logic error",id:"logic-error",level:2},{value:"Memory error",id:"memory-error",level:2},{value:"Null pointer dereference",id:"null-pointer-dereference",level:2},{value:"Perf regression",id:"perf-regression",level:2},{value:"Resource leak",id:"resource-leak",level:2},{value:"Runtime exception",id:"runtime-exception",level:2},{value:"Sensitive data flow",id:"sensitive-data-flow",level:2},{value:"Ungated code",id:"ungated-code",level:2},{value:"User defined property",id:"user-defined-property",level:2}];function d(e){const s={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(s.p,{children:"Here are all the categories that issue types might belong to in Infer. Some issue types have no associated category at the moment. This usually indicates that the issue type is not yet mature enough to be used."}),"\n",(0,l.jsx)(s.h2,{id:"concurrency",children:"Concurrency"}),"\n",(0,l.jsx)(s.p,{children:"Concurrent accesses to the same resource conflict in a way that can give incorrect results, block progress, or result in undefined behaviour."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#deadlock",children:"DEADLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#guardedby_violation",children:"GUARDEDBY_VIOLATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#static_constructor_stall",children:"STATIC_CONSTRUCTOR_STALL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"logic-error",children:"Logic error"}),"\n",(0,l.jsx)(s.p,{children:"Something that does not make sense and the sign of a potential programming error."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#dead_store",children:"DEAD_STORE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"memory-error",children:"Memory error"}),"\n",(0,l.jsx)(s.p,{children:"Incorrect handling of pointers that isn't a null pointer dereference, but can still result in undefined behaviour and crashes."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#cxx_string_captured_in_block",children:"CXX_STRING_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nsstring_internal_ptr_captured_in_block",children:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"null-pointer-dereference",children:"Null pointer dereference"}),"\n",(0,l.jsx)(s.p,{children:"The null pointer is used where a valid pointer is required, causing a memory fault and a crash. For example, it is dereferenced."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_dereference",children:"NULL_DEREFERENCE"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"perf-regression",children:"Perf regression"}),"\n",(0,l.jsx)(s.p,{children:"Unnecessary (or blocking) computation is performed, potentially causing a performance or responsiveness regression."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#config_impact",children:"CONFIG_IMPACT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#lock_on_ui_thread",children:"LOCK_ON_UI_THREAD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#strict_mode_violation",children:"STRICT_MODE_VIOLATION"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"resource-leak",children:"Resource leak"}),"\n",(0,l.jsx)(s.p,{children:"A resource (for example memory, or a file descriptor) has been manually allocated but not released, possibly creating memory pressure over time or even incorrect results."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#biabduction_memory_leak",children:"BIABDUCTION_MEMORY_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#biabduction_retain_cycle",children:"BIABDUCTION_RETAIN_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#captured_strong_self",children:"CAPTURED_STRONG_SELF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_fragment_retains_view",children:"CHECKERS_FRAGMENT_RETAINS_VIEW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#resource_leak",children:"RESOURCE_LEAK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#self_in_block_passed_to_init",children:"SELF_IN_BLOCK_PASSED_TO_INIT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"runtime-exception",children:"Runtime exception"}),"\n",(0,l.jsx)(s.p,{children:"A runtime exception can occur and potentially crash the program."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_generator",children:"BAD_GENERATOR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_generator_latent",children:"BAD_GENERATOR_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#infinite_recursion",children:"INFINITE_RECURSION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#missing_required_prop",children:"MISSING_REQUIRED_PROP"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"sensitive-data-flow",children:"Sensitive data flow"}),"\n",(0,l.jsx)(s.p,{children:"Sensitive data is flowing where it shouldn't."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#lineage_flow",children:"LINEAGE_FLOW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#scope_leakage",children:"SCOPE_LEAKAGE"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"ungated-code",children:"Ungated code"}),"\n",(0,l.jsx)(s.p,{children:"Code must be under a gating mechanism but isn't."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#config_impact_strict",children:"CONFIG_IMPACT_STRICT"})}),"\n"]}),"\n",(0,l.jsx)(s.h2,{id:"user-defined-property",children:"User defined property"}),"\n",(0,l.jsx)(s.p,{children:"A user defined (custom) property is violated."}),"\n",(0,l.jsx)(s.p,{children:"Issue types in this category:"}),"\n",(0,l.jsxs)(s.ul,{children:["\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#topl_error",children:"TOPL_ERROR"})}),"\n",(0,l.jsx)(s.li,{children:(0,l.jsx)(s.a,{href:"/docs/next/all-issue-types#topl_error_latent",children:"TOPL_ERROR_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,l.jsx)(s,{...e,children:(0,l.jsx)(d,{...e})}):d(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>t,x:()=>c});var l=n(6540);const i={},r=l.createContext(i);function t(e){const s=l.useContext(r);return l.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),l.createElement(r.Provider,{value:s},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/8fdeae25.904d52c1.js b/assets/js/8fdeae25.5a49904a.js
similarity index 55%
rename from assets/js/8fdeae25.904d52c1.js
rename to assets/js/8fdeae25.5a49904a.js
index 67893e0777b..fb91e920453 100644
--- a/assets/js/8fdeae25.904d52c1.js
+++ b/assets/js/8fdeae25.5a49904a.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9437],{930:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var l=s(4848),i=s(8453);const r={title:"Pulse",description:"General-purpose memory and value analysis engine."},t=void 0,c={id:"checker-pulse",title:"Pulse",description:"General-purpose memory and value analysis engine.",source:"@site/docs/checker-pulse.md",sourceDirName:".",slug:"/checker-pulse",permalink:"/docs/next/checker-pulse",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Pulse",description:"General-purpose memory and value analysis engine."},sidebar:"docs",previous:{title:"Parameter Not Null Checked",permalink:"/docs/next/checker-parameter-not-null-checked"},next:{title:"Purity",permalink:"/docs/next/checker-purity"}},a={},d=[{value:"What is Infer?",id:"what-is-infer",level:2},{value:"Latent Issues",id:"latent-issues",level:2},{value:"Unknown Functions",id:"unknown-functions",level:2},{value:"Pulse x Nullsafe",id:"pulse-x-nullsafe",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function o(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,l.jsxs)(n.p,{children:["Activate with ",(0,l.jsx)(n.code,{children:"--pulse"}),"."]}),"\n",(0,l.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,l.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,l.jsx)(n.li,{children:"Erlang: Experimental"}),"\n",(0,l.jsx)(n.li,{children:"Hack: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,l.jsxs)(n.h2,{id:"what-is-infer",children:["What is Infer",":Pulse","?"]}),"\n",(0,l.jsxs)(n.p,{children:["Pulse is an interprocedural memory safety analysis. Pulse can detect, for instance, ",(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"Null dereferences"})," in Java. Errors are only reported when all conditions on the erroneous path are true regardless of input. Pulse should gradually replace the original ",(0,l.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"})," analysis of Infer. An example of a Null dereference found by Pulse is given below."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"class Person {\n Person emergencyContact;\n String address;\n\n Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n void create() {\n Person p = new Person();\n Person c = p.getEmergencyContact();\n // Null dereference here\n System.out.println(c.address);\n }\n\n void printContact(Person p) {\n // No null dereference, as we don't know anything about `p`\n System.out.println(p.getEmergencyContact().address);\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"How to run pulse for Java:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"infer run --pulse -- javac Test.java\n"})}),"\n",(0,l.jsxs)(n.p,{children:["Pulse reports a Null dereference on this file on ",(0,l.jsx)(n.code,{children:"create()"}),", as it tries to access the field ",(0,l.jsx)(n.code,{children:"address"})," of object ",(0,l.jsx)(n.code,{children:"c"}),", and ",(0,l.jsx)(n.code,{children:"c"})," has value ",(0,l.jsx)(n.code,{children:"null"}),". In contrast, Pulse gives no report for ",(0,l.jsx)(n.code,{children:"printContact(Person p)"}),", as we cannot be sure that ",(0,l.jsx)(n.code,{children:"p.getEmergencyContact()"})," will return ",(0,l.jsx)(n.code,{children:"null"}),". But, thanks to the fact that the analysis is ",(0,l.jsx)(n.em,{children:"inter-procedural"}),", Pulse will report a Null dereference on calls to ",(0,l.jsx)(n.code,{children:"printContact(p)"})," when it detects that ",(0,l.jsx)(n.code,{children:"p"})," is null."]}),"\n",(0,l.jsx)(n.h2,{id:"latent-issues",children:"Latent Issues"}),"\n",(0,l.jsxs)(n.p,{children:["When an error can occur only on some values of the parameters of the current function, Pulse does not report an issue. Such issues are called ",(0,l.jsx)(n.em,{children:"latent"}),". But, if Pulse then sees a call site at which all the conditions for the error are satisfied then the error becomes ",(0,l.jsx)(n.em,{children:"manifest"})," and is reported. This example (in C) illustrates how latent issues are created and then reported when they become manifest:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"// for more realism, imagine that this function does other things as well\nvoid set_to_null_if_positive(int n, int* p) {\n if (n > 0) {\n p = NULL;\n }\n}\n\nvoid latent_null_dereference(int n, int* p) {\n set_to_null_if_positive(n, p);\n *p = 42; // NULL dereference! but only if n > 0 so no report yet\n}\n\nvoid manifest_error(int *p) {\n // no way to avoid the bug here => Pulse reports an error\n latent_null_dereference(1, p);\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"unknown-functions",children:"Unknown Functions"}),"\n",(0,l.jsx)(n.p,{children:"In order to avoid false positives, Pulse makes optimistic assumptions about calls to unknown functions. Unknown functions (or unknown methods) are functions for which Infer didn't find any code. For example, it could be because the function belongs to a third-party library and we know only its signature, or because a function is made through a function pointer that Pulse wasn't able to resolve to a concrete function. In either case, Pulse will scramble the parts of the state reachable from the parameters of the call. In general, this helps avoid false positives but note that this may cause false negatives as well as false positives:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"void unknown(int* p); // third-party code that does [*p = 5]\n // Infer doesn't have access to that code\n\nvoid false_negative() {\n int* x = (int*) malloc(sizeof(int));\n if (x) {\n // unknown call to x makes Pulse forget that x was allocated, in case it frees x\n unknown(x);\n }\n} // no memory leak reported: false negative!\n\nvoid false_positive(int *x) {\n unknown(x); // this sets *x to 5\n if (x != 5) {\n // unreachable\n int* p = NULL;\n *p = 42; // false positive reported here\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"You can check if a given function called any unknown functions by inspecting its Pulse summary. For example, for the code above:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-console",children:"$ infer --pulse-only -- clang -c unknown_code.c\n No issues found\n$ infer debug --procedures --procedures-filter 'false_negative' --procedures-summary\n...\n skipped_calls={ unknown -> call to skipped function occurs here }\n"})}),"\n",(0,l.jsx)(n.h2,{id:"pulse-x-nullsafe",children:"Pulse x Nullsafe"}),"\n",(0,l.jsxs)(n.p,{children:["Nullsafe is a type checker for ",(0,l.jsx)(n.code,{children:"@Nullable"})," annotations for Java. Classes following the Nullsafe discipline are annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["Consider the classes ",(0,l.jsx)(n.code,{children:"Person"})," and ",(0,l.jsx)(n.code,{children:"Registry"})," from the previous example. Assuming that class ",(0,l.jsx)(n.code,{children:"Person"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". In this case, we also annotate ",(0,l.jsx)(n.code,{children:"getEmergencyContact()"})," with ",(0,l.jsx)(n.code,{children:"@Nullable"}),", to make explicit that this method can return the ",(0,l.jsx)(n.code,{children:"null"})," value. There is still the risk that classes depending on ",(0,l.jsx)(n.code,{children:"Person"})," have Null dereferences. In this case, Pulse would report a Null dereference on ",(0,l.jsx)(n.code,{children:"Registry"}),". It could also be the case that class ",(0,l.jsx)(n.code,{children:"Registry"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". By default Pulse reports on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files too, see the ",(0,l.jsx)(n.code,{children:"--pulse-nullsafe-report-npe"})," option (Facebook-specific: Pulse does not report on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files)."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"@Nullsafe(Nullsafe.Mode.LOCAL)\nclass Person {\n Person emergencyContact;\n String address;\n\n @Nullable Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n ... // Pulse reports here\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,l.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_generator",children:"BAD_GENERATOR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_generator_latent",children:"BAD_GENERATOR_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return",children:"BAD_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return_latent",children:"BAD_RETURN_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#config_usage",children:"CONFIG_USAGE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var l=s(6540);const i={},r=l.createContext(i);function t(e){const n=l.useContext(r);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),l.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9437],{930:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>t,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var l=s(4848),i=s(8453);const r={title:"Pulse",description:"General-purpose memory and value analysis engine."},t=void 0,c={id:"checker-pulse",title:"Pulse",description:"General-purpose memory and value analysis engine.",source:"@site/docs/checker-pulse.md",sourceDirName:".",slug:"/checker-pulse",permalink:"/docs/next/checker-pulse",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Pulse",description:"General-purpose memory and value analysis engine."},sidebar:"docs",previous:{title:"Parameter Not Null Checked",permalink:"/docs/next/checker-parameter-not-null-checked"},next:{title:"Purity",permalink:"/docs/next/checker-purity"}},a={},d=[{value:"What is Infer?",id:"what-is-infer",level:2},{value:"Latent Issues",id:"latent-issues",level:2},{value:"Unknown Functions",id:"unknown-functions",level:2},{value:"Pulse x Nullsafe",id:"pulse-x-nullsafe",level:2},{value:"List of Issue Types",id:"list-of-issue-types",level:2}];function o(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.p,{children:"General-purpose memory and value analysis engine."}),"\n",(0,l.jsxs)(n.p,{children:["Activate with ",(0,l.jsx)(n.code,{children:"--pulse"}),"."]}),"\n",(0,l.jsx)(n.p,{children:"Supported languages:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:"C/C++/ObjC: Yes"}),"\n",(0,l.jsx)(n.li,{children:"C#/.Net: No"}),"\n",(0,l.jsx)(n.li,{children:"Erlang: Experimental"}),"\n",(0,l.jsx)(n.li,{children:"Hack: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Java: Yes"}),"\n",(0,l.jsx)(n.li,{children:"Python: No"}),"\n"]}),"\n",(0,l.jsxs)(n.h2,{id:"what-is-infer",children:["What is Infer",":Pulse","?"]}),"\n",(0,l.jsxs)(n.p,{children:["Pulse is an interprocedural memory safety analysis. Pulse can detect, for instance, ",(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"Null dereferences"})," in Java. Errors are only reported when all conditions on the erroneous path are true regardless of input. Pulse should gradually replace the original ",(0,l.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"})," analysis of Infer. An example of a Null dereference found by Pulse is given below."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"class Person {\n Person emergencyContact;\n String address;\n\n Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n void create() {\n Person p = new Person();\n Person c = p.getEmergencyContact();\n // Null dereference here\n System.out.println(c.address);\n }\n\n void printContact(Person p) {\n // No null dereference, as we don't know anything about `p`\n System.out.println(p.getEmergencyContact().address);\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"How to run pulse for Java:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-bash",children:"infer run --pulse -- javac Test.java\n"})}),"\n",(0,l.jsxs)(n.p,{children:["Pulse reports a Null dereference on this file on ",(0,l.jsx)(n.code,{children:"create()"}),", as it tries to access the field ",(0,l.jsx)(n.code,{children:"address"})," of object ",(0,l.jsx)(n.code,{children:"c"}),", and ",(0,l.jsx)(n.code,{children:"c"})," has value ",(0,l.jsx)(n.code,{children:"null"}),". In contrast, Pulse gives no report for ",(0,l.jsx)(n.code,{children:"printContact(Person p)"}),", as we cannot be sure that ",(0,l.jsx)(n.code,{children:"p.getEmergencyContact()"})," will return ",(0,l.jsx)(n.code,{children:"null"}),". But, thanks to the fact that the analysis is ",(0,l.jsx)(n.em,{children:"inter-procedural"}),", Pulse will report a Null dereference on calls to ",(0,l.jsx)(n.code,{children:"printContact(p)"})," when it detects that ",(0,l.jsx)(n.code,{children:"p"})," is null."]}),"\n",(0,l.jsx)(n.h2,{id:"latent-issues",children:"Latent Issues"}),"\n",(0,l.jsxs)(n.p,{children:["When an error can occur only on some values of the parameters of the current function, Pulse does not report an issue. Such issues are called ",(0,l.jsx)(n.em,{children:"latent"}),". But, if Pulse then sees a call site at which all the conditions for the error are satisfied then the error becomes ",(0,l.jsx)(n.em,{children:"manifest"})," and is reported. This example (in C) illustrates how latent issues are created and then reported when they become manifest:"]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"// for more realism, imagine that this function does other things as well\nvoid set_to_null_if_positive(int n, int* p) {\n if (n > 0) {\n p = NULL;\n }\n}\n\nvoid latent_null_dereference(int n, int* p) {\n set_to_null_if_positive(n, p);\n *p = 42; // NULL dereference! but only if n > 0 so no report yet\n}\n\nvoid manifest_error(int *p) {\n // no way to avoid the bug here => Pulse reports an error\n latent_null_dereference(1, p);\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"unknown-functions",children:"Unknown Functions"}),"\n",(0,l.jsx)(n.p,{children:"In order to avoid false positives, Pulse makes optimistic assumptions about calls to unknown functions. Unknown functions (or unknown methods) are functions for which Infer didn't find any code. For example, it could be because the function belongs to a third-party library and we know only its signature, or because a function is made through a function pointer that Pulse wasn't able to resolve to a concrete function. In either case, Pulse will scramble the parts of the state reachable from the parameters of the call. In general, this helps avoid false positives but note that this may cause false negatives as well as false positives:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-c",children:"void unknown(int* p); // third-party code that does [*p = 5]\n // Infer doesn't have access to that code\n\nvoid false_negative() {\n int* x = (int*) malloc(sizeof(int));\n if (x) {\n // unknown call to x makes Pulse forget that x was allocated, in case it frees x\n unknown(x);\n }\n} // no memory leak reported: false negative!\n\nvoid false_positive(int *x) {\n unknown(x); // this sets *x to 5\n if (x != 5) {\n // unreachable\n int* p = NULL;\n *p = 42; // false positive reported here\n }\n}\n"})}),"\n",(0,l.jsx)(n.p,{children:"You can check if a given function called any unknown functions by inspecting its Pulse summary. For example, for the code above:"}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-console",children:"$ infer --pulse-only -- clang -c unknown_code.c\n No issues found\n$ infer debug --procedures --procedures-filter 'false_negative' --procedures-summary\n...\n skipped_calls={ unknown -> call to skipped function occurs here }\n"})}),"\n",(0,l.jsx)(n.h2,{id:"pulse-x-nullsafe",children:"Pulse x Nullsafe"}),"\n",(0,l.jsxs)(n.p,{children:["Nullsafe is a type checker for ",(0,l.jsx)(n.code,{children:"@Nullable"})," annotations for Java. Classes following the Nullsafe discipline are annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),"."]}),"\n",(0,l.jsxs)(n.p,{children:["Consider the classes ",(0,l.jsx)(n.code,{children:"Person"})," and ",(0,l.jsx)(n.code,{children:"Registry"})," from the previous example. Assuming that class ",(0,l.jsx)(n.code,{children:"Person"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". In this case, we also annotate ",(0,l.jsx)(n.code,{children:"getEmergencyContact()"})," with ",(0,l.jsx)(n.code,{children:"@Nullable"}),", to make explicit that this method can return the ",(0,l.jsx)(n.code,{children:"null"})," value. There is still the risk that classes depending on ",(0,l.jsx)(n.code,{children:"Person"})," have Null dereferences. In this case, Pulse would report a Null dereference on ",(0,l.jsx)(n.code,{children:"Registry"}),". It could also be the case that class ",(0,l.jsx)(n.code,{children:"Registry"})," is annotated with ",(0,l.jsx)(n.code,{children:"@Nullsafe"}),". By default Pulse reports on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files too, see the ",(0,l.jsx)(n.code,{children:"--pulse-nullsafe-report-npe"})," option (Facebook-specific: Pulse does not report on ",(0,l.jsx)(n.code,{children:"@Nullsafe"})," files)."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-java",children:"@Nullsafe(Nullsafe.Mode.LOCAL)\nclass Person {\n Person emergencyContact;\n String address;\n\n @Nullable Person getEmergencyContact() {\n return this.emergencyContact;\n }\n}\n\nclass Registry {\n ... // Pulse reports here\n}\n"})}),"\n",(0,l.jsx)(n.h2,{id:"list-of-issue-types",children:"List of Issue Types"}),"\n",(0,l.jsx)(n.p,{children:"The following issue types are reported by this checker:"}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg",children:"BAD_ARG"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_arg_latent",children:"BAD_ARG_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_generator",children:"BAD_GENERATOR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_generator_latent",children:"BAD_GENERATOR_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key",children:"BAD_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_key_latent",children:"BAD_KEY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map",children:"BAD_MAP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_map_latent",children:"BAD_MAP_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record",children:"BAD_RECORD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_record_latent",children:"BAD_RECORD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return",children:"BAD_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#bad_return_latent",children:"BAD_RETURN_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#config_usage",children:"CONFIG_USAGE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#data_flow_to_sink",children:"DATA_FLOW_TO_SINK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#infinite_recursion",children:"INFINITE_RECURSION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_c",children:"MEMORY_LEAK_C"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#memory_leak_cpp",children:"MEMORY_LEAK_CPP"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"NIL_BLOCK_CALL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs",children:"NO_MATCH_OF_RHS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference",children:"NULLPTR_DEREFERENCE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument",children:"NULL_ARGUMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#null_argument_latent",children:"NULL_ARGUMENT_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_const_refable",children:"PULSE_CONST_REFABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle",children:"RETAIN_CYCLE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#taint_error",children:"TAINT_ERROR"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete",children:"USE_AFTER_DELETE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free",children:"USE_AFTER_FREE"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_free_latent",children:"USE_AFTER_FREE_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime",children:"USE_AFTER_LIFETIME"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation",children:"VECTOR_INVALIDATION"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.a,{href:"/docs/next/all-issue-types#vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var l=s(6540);const i={},r=l.createContext(i);function t(e){const n=l.useContext(r);return l.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),l.createElement(r.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c359af60.1278ce61.js b/assets/js/c359af60.1278ce61.js
deleted file mode 100644
index dcbf7db0074..00000000000
--- a/assets/js/c359af60.1278ce61.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2316],{28:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>o});var r=s(4848),i=s(8453);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 categories of issue types",permalink:"/docs/next/all-categories"},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_GENERATOR",id:"bad_generator",level:2},{value:"BAD_GENERATOR_LATENT",id:"bad_generator_latent",level:2},{value:"BAD_KEY",id:"bad_key",level:2},{value:"BAD_KEY_LATENT",id:"bad_key_latent",level:2},{value:"BAD_MAP",id:"bad_map",level:2},{value:"BAD_MAP_LATENT",id:"bad_map_latent",level:2},{value:"BAD_RECORD",id:"bad_record",level:2},{value:"BAD_RECORD_LATENT",id:"bad_record_latent",level:2},{value:"BAD_RETURN",id:"bad_return",level:2},{value:"BAD_RETURN_LATENT",id:"bad_return_latent",level:2},{value:"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:"COMPARED_TO_NULL_AND_DEREFERENCED",id:"compared_to_null_and_dereferenced",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:"CXX_REF_CAPTURED_IN_BLOCK",id:"cxx_ref_captured_in_block",level:2},{value:"CXX_STRING_CAPTURED_IN_BLOCK",id:"cxx_string_captured_in_block",level:2},{value:"DANGLING_POINTER_DEREFERENCE",id:"dangling_pointer_dereference",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:"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:"INTEGER_OVERFLOW_L1",id:"integer_overflow_l1",level:2},{value:"INTEGER_OVERFLOW_L2",id:"integer_overflow_l2",level:2},{value:"INTEGER_OVERFLOW_L5",id:"integer_overflow_l5",level:2},{value:"INTEGER_OVERFLOW_U5",id:"integer_overflow_u5",level:2},{value:"INTERFACE_NOT_THREAD_SAFE",id:"interface_not_thread_safe",level:2},{value:"INVALID_SIL",id:"invalid_sil",level:2},{value:"INVARIANT_CALL",id:"invariant_call",level:2},{value:"IPC_ON_UI_THREAD",id:"ipc_on_ui_thread",level:2},{value:"LAB_RESOURCE_LEAK",id:"lab_resource_leak",level:2},{value:"LINEAGE_FLOW",id:"lineage_flow",level:2},{value:"LOCKLESS_VIOLATION",id:"lockless_violation",level:2},{value:"LOCK_CONSISTENCY_VIOLATION",id:"lock_consistency_violation",level:2},{value:"Fixing Lock Consistency Violation reports",id:"fixing-lock-consistency-violation-reports",level:3},{value:"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:"MUTUAL_RECURSION_CYCLE",id:"mutual_recursion_cycle",level:2},{value:"NIL_BLOCK_CALL",id:"nil_block_call",level:2},{value:"NIL_BLOCK_CALL_LATENT",id:"nil_block_call_latent",level:2},{value:"NIL_INSERTION_INTO_COLLECTION",id:"nil_insertion_into_collection",level:2},{value:"Arrays",id:"arrays",level:3},{value:"Dictionaries",id:"dictionaries",level:3},{value:"NIL_INSERTION_INTO_COLLECTION_LATENT",id:"nil_insertion_into_collection_latent",level:2},{value:"NIL_MESSAGING_TO_NON_POD",id:"nil_messaging_to_non_pod",level:2},{value:"NIL_MESSAGING_TO_NON_POD_LATENT",id:"nil_messaging_to_non_pod_latent",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY",id:"no_matching_branch_in_try",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY_LATENT",id:"no_matching_branch_in_try_latent",level:2},{value:"NO_MATCHING_CASE_CLAUSE",id:"no_matching_case_clause",level:2},{value:"NO_MATCHING_CASE_CLAUSE_LATENT",id:"no_matching_case_clause_latent",level:2},{value:"NO_MATCHING_ELSE_CLAUSE",id:"no_matching_else_clause",level:2},{value:"NO_MATCHING_ELSE_CLAUSE_LATENT",id:"no_matching_else_clause_latent",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE",id:"no_matching_function_clause",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE_LATENT",id:"no_matching_function_clause_latent",level:2},{value:"NO_MATCH_OF_RHS",id:"no_match_of_rhs",level:2},{value:"NO_MATCH_OF_RHS_LATENT",id:"no_match_of_rhs_latent",level:2},{value:"NO_TRUE_BRANCH_IN_IF",id:"no_true_branch_in_if",level:2},{value:"NO_TRUE_BRANCH_IN_IF_LATENT",id:"no_true_branch_in_if_latent",level:2},{value:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK",id:"nsstring_internal_ptr_captured_in_block",level:2},{value:"NULLPTR_DEREFERENCE",id:"nullptr_dereference",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java",level:3},{value:"Null dereference in C",id:"null-dereference-in-c",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS",id:"nullptr_dereference_in_nullsafe_class",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java-1",level:3},{value:"Null dereference in C",id:"null-dereference-in-c-1",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c-1",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT",id:"nullptr_dereference_in_nullsafe_class_latent",level:2},{value:"NULLPTR_DEREFERENCE_LATENT",id:"nullptr_dereference_latent",level:2},{value:"NULL_ARGUMENT",id:"null_argument",level:2},{value:"NULL_ARGUMENT_LATENT",id:"null_argument_latent",level:2},{value:"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_CANNOT_INSTANTIATE_ABSTRACT_CLASS",id:"pulse_cannot_instantiate_abstract_class",level:2},{value:"PULSE_CONST_REFABLE",id:"pulse_const_refable",level:2},{value:"PULSE_DICT_MISSING_KEY",id:"pulse_dict_missing_key",level:2},{value:"PULSE_DYNAMIC_TYPE_MISMATCH",id:"pulse_dynamic_type_mismatch",level:2},{value:"PULSE_READONLY_SHARED_PTR_PARAM",id:"pulse_readonly_shared_ptr_param",level:2},{value:"PULSE_REFERENCE_STABILITY",id:"pulse_reference_stability",level:2},{value:"PULSE_RESOURCE_LEAK",id:"pulse_resource_leak",level:2},{value:"PULSE_TRANSITIVE_ACCESS",id:"pulse_transitive_access",level:2},{value:"PULSE_UNAWAITED_AWAITABLE",id:"pulse_unawaited_awaitable",level:2},{value:"PULSE_UNFINISHED_BUILDER",id:"pulse_unfinished_builder",level:2},{value:"PULSE_UNINITIALIZED_CONST",id:"pulse_uninitialized_const",level:2},{value:"PULSE_UNINITIALIZED_METHOD",id:"pulse_uninitialized_method",level:2},{value:"PULSE_UNINITIALIZED_VALUE",id:"pulse_uninitialized_value",level:2},{value:"PULSE_UNNECESSARY_COPY",id:"pulse_unnecessary_copy",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT",id:"pulse_unnecessary_copy_assignment",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST",id:"pulse_unnecessary_copy_assignment_const",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE",id:"pulse_unnecessary_copy_assignment_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE",id:"pulse_unnecessary_copy_intermediate",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST",id:"pulse_unnecessary_copy_intermediate_const",level:2},{value:"PULSE_UNNECESSARY_COPY_MOVABLE",id:"pulse_unnecessary_copy_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL",id:"pulse_unnecessary_copy_optional",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST",id:"pulse_unnecessary_copy_optional_const",level:2},{value:"PULSE_UNNECESSARY_COPY_RETURN",id:"pulse_unnecessary_copy_return",level:2},{value:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT",id:"pulse_unnecessary_copy_thrift_assignment",level:2},{value:"PURE_FUNCTION",id:"pure_function",level:2},{value:"REGEX_OP_ON_UI_THREAD",id:"regex_op_on_ui_thread",level:2},{value:"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:"RETAIN_CYCLE_NO_WEAK_INFO",id:"retain_cycle_no_weak_info",level:2},{value:"SCOPE_LEAKAGE",id:"scope_leakage",level:2},{value:"SELF_IN_BLOCK_PASSED_TO_INIT",id:"self_in_block_passed_to_init",level:2},{value:"SENSITIVE_DATA_FLOW",id:"sensitive_data_flow",level:2},{value:"STACK_VARIABLE_ADDRESS_ESCAPE",id:"stack_variable_address_escape",level:2},{value:"STARVATION",id:"starvation",level:2},{value:"STATIC_CONSTRUCTOR_STALL",id:"static_constructor_stall",level:2},{value:"STATIC_INITIALIZATION_ORDER_FIASCO",id:"static_initialization_order_fiasco",level:2},{value:"STRICT_MODE_VIOLATION",id:"strict_mode_violation",level:2},{value:"STRONG_SELF_NOT_CHECKED",id:"strong_self_not_checked",level:2},{value:"TAINT_ERROR",id:"taint_error",level:2},{value:"THREAD_SAFETY_VIOLATION",id:"thread_safety_violation",level:2},{value:"Thread-safety: What is a data race",id:"thread-safety-what-is-a-data-race",level:3},{value:"Thread-safety: Potential fixes",id:"thread-safety-potential-fixes",level:3},{value:"Thread-safety: Conditions checked before reporting",id:"thread-safety-conditions-checked-before-reporting",level:3},{value:"Thread-safety: Thread annotations recognized by RacerD",id:"thread-safety-thread-annotations-recognized-by-racerd",level:3},{value:"Thread-safety: Other annotations and what they do",id:"thread-safety-other-annotations-and-what-they-do",level:3},{value:"TOPL_ERROR",id:"topl_error",level:2},{value:"TOPL_ERROR_LATENT",id:"topl_error_latent",level:2},{value:"USE_AFTER_DELETE",id:"use_after_delete",level:2},{value:"USE_AFTER_DELETE_LATENT",id:"use_after_delete_latent",level:2},{value:"USE_AFTER_FREE",id:"use_after_free",level:2},{value:"USE_AFTER_FREE_LATENT",id:"use_after_free_latent",level:2},{value:"USE_AFTER_LIFETIME",id:"use_after_lifetime",level:2},{value:"USE_AFTER_LIFETIME_LATENT",id:"use_after_lifetime_latent",level:2},{value:"VECTOR_INVALIDATION",id:"vector_invalidation",level:2},{value:"VECTOR_INVALIDATION_LATENT",id:"vector_invalidation_latent",level:2},{value:"WEAK_SELF_IN_NO_ESCAPE_BLOCK",id:"weak_self_in_no_escape_block",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Here is an overview of the issue types currently reported by Infer."}),"\n",(0,r.jsx)(n.h2,{id:"arbitrary_code_execution_under_lock",children:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Arbitrary Code Execution Under lock" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"bad_arg",children:"BAD_ARG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"badarg"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to concatenate the number ",(0,r.jsx)(n.code,{children:"3"})," with the list ",(0,r.jsx)(n.code,{children:"[1,2]"})," gives ",(0,r.jsx)(n.code,{children:"badarg"})," error because ",(0,r.jsx)(n.code,{children:"3"})," is not a list."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n 3 ++ [1,2]. // badarg error\n"})}),"\n",(0,r.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,r.jsx)(n.code,{children:"3"})," raises no error in Erlang."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"g() ->\n [1,2] ++ 3. // no error. Result: [1,2|3]\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_arg_latent",children:"BAD_ARG_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_arg",children:"BAD_ARG"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_generator",children:"BAD_GENERATOR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Bad generator in Erlang: Reports an error when a wrong type is used in a generator. Corresponds to the ",(0,r.jsx)(n.code,{children:"bad_generator"})," error in the Erlang runtime."]}),"\n",(0,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"list_instead_of_map() ->\n M = [],\n [{K, V} || K := V <- M]\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_generator_latent",children:"BAD_GENERATOR_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_generator",children:"BAD_GENERATOR"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_key",children:"BAD_KEY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badkey,K}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to update the key ",(0,r.jsx)(n.code,{children:"2"})," in ",(0,r.jsx)(n.code,{children:"M"})," gives ",(0,r.jsx)(n.code,{children:"{badkey,2}"})," error because ",(0,r.jsx)(n.code,{children:"2"})," is not present as a key in ",(0,r.jsx)(n.code,{children:"M"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n M = #{},\n M#{2 := 3}.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"bad_key_latent",children:"BAD_KEY_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_key",children:"BAD_KEY"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_map",children:"BAD_MAP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badmap,...}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to update ",(0,r.jsx)(n.code,{children:"L"})," as if it was a map gives ",(0,r.jsx)(n.code,{children:"{badmap,[1,2,3]}"})," error because ",(0,r.jsx)(n.code,{children:"L"})," is actually a list (",(0,r.jsx)(n.code,{children:"[1,2,3]"}),")."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n L = [1,2,3],\n L#{1 => 2}.\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_map_latent",children:"BAD_MAP_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_map",children:"BAD_MAP"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_record",children:"BAD_RECORD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badrecord,Name}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, accessing ",(0,r.jsx)(n.code,{children:"R"})," as a ",(0,r.jsx)(n.code,{children:"person"})," record gives ",(0,r.jsx)(n.code,{children:"{badrecord,person}"})," error because ",(0,r.jsx)(n.code,{children:"R"})," is ",(0,r.jsx)(n.code,{children:"rabbit"})," (even though both share the ",(0,r.jsx)(n.code,{children:"name"})," field)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"bad_record_latent",children:"BAD_RECORD_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_record",children:"BAD_RECORD"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_return",children:"BAD_RETURN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Bad Return" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example, this function returns an integer, while the spec says it returns an atom."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"-spec f() -> atom().\nf() -> 1.\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that this will ",(0,r.jsx)(n.em,{children:"not"})," lead to a runtime error when running the Erlang program."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_return_latent",children:"BAD_RETURN_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Bad Return Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_return",children:"BAD_RETURN"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"biabduction_memory_leak",children:"BIABDUCTION_MEMORY_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"biabduction_retain_cycle",children:"BIABDUCTION_RETAIN_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#retain_cycle",children:"RETAIN_CYCLE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Block Parameter Not Null Checked" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-parameter-not-null-checked",children:"parameter-not-null-checked"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"})," first. If a ",(0,r.jsx)(n.code,{children:"nil"})," block is passed to\nthe method, then this will cause a crash. For example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nPossible solutions are adding a check for ",(0,r.jsx)(n.code,{children:"nil"}),", or making sure that the method\nis not ever called with ",(0,r.jsx)(n.code,{children:"nil"}),". When an argument will never be ",(0,r.jsx)(n.code,{children:"nil"}),", you can add\nthe annotation ",(0,r.jsx)(n.code,{children:"nonnull"})," to the argument's type, to tell Infer (and the type\nsystem), that the argument won't be ",(0,r.jsx)(n.code,{children:"nil"}),". This will silence the warning."]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L1" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.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,r.jsxs)(n.p,{children:["For example, ",(0,r.jsx)(n.code,{children:"int a[3]; a[5] = 42;"})," generates a ",(0,r.jsx)(n.code,{children:"BUFFER_OVERRUN_L1"})," on ",(0,r.jsx)(n.code,{children:"a[5] = 42;"}),"."]}),"\n",(0,r.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,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,r.jsx)(n.em,{children:"must"})," be unsafe. For example, array size: ",(0,r.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,r.jsx)(n.code,{children:"[5,5]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,r.jsx)(n.code,{children:"L1"}),", when it ",(0,r.jsx)(n.em,{children:"may"})," be unsafe. For example, array size:",(0,r.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L5"}),": The least faithful report, when there is an interval top. For example, array size:\n",(0,r.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,r.jsx)(n.code,{children:"[-oo,+oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L4"}),": More faithful report than ",(0,r.jsx)(n.code,{children:"L5"}),", when there is an infinity value. For example, array size:\n",(0,r.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,r.jsx)(n.code,{children:"[0, +oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L3"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"S2"}),": An array access is unsafe by symbolic values. For example, array size: ",(0,r.jsx)(n.code,{children:"[n,n]"}),", offset\n",(0,r.jsx)(n.code,{children:"[n,+oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"U5"}),": An array access is unsafe by unknown values, which are usually from unknown function\ncalls."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l2",children:"BUFFER_OVERRUN_L2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l3",children:"BUFFER_OVERRUN_L3"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L3" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l4",children:"BUFFER_OVERRUN_L4"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L4" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l5",children:"BUFFER_OVERRUN_L5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_s2",children:"BUFFER_OVERRUN_S2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun S2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_u5",children:"BUFFER_OVERRUN_U5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun U5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"captured_strong_self",children:"CAPTURED_STRONG_SELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Captured strongSelf" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check is about when a strong pointer to ",(0,r.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,r.jsx)(n.p,{children:"This will happen in one of two cases generally:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["One uses ",(0,r.jsx)(n.code,{children:"weakSelf"})," but forgot to declare it weak first."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"})," Replace the first line with ",(0,r.jsx)(n.code,{children:"__weak __typeof(self) weakSelf = self;"}),"."]}),"\n",(0,r.jsxs)(n.ol,{start:"2",children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["One is using ",(0,r.jsx)(n.code,{children:"strongSelf"}),", declared in a block, in another inner block.\nThe retain cycle is avoided in the outer block because ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a\nlocal variable of the block. If ",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this example, ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a captured variable of the inner block, and this could cause retain cycles."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"})," Use a new pointer to self local to the inner block. In the example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Or, to improve readability, move the inner block logic into a separate method."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Allocates Memory" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@NoAllocation"})," transitively calls ",(0,r.jsx)(n.code,{children:"new"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"class C implements I {\n @NoAllocation\n void directlyAllocatingMethod() {\n new Object();\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Annotation Reachability Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with an annotation ",(0,r.jsx)(n.code,{children:"@A"})," transitively calls a method annotated ",(0,r.jsx)(n.code,{children:"@B"})," where the combination of annotations is forbidden (for example, ",(0,r.jsx)(n.code,{children:"@UiThread"})," calling ",(0,r.jsx)(n.code,{children:"@WorkerThread"}),")."]}),"\n",(0,r.jsx)(n.h2,{id:"checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Expensive Method Called" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@PerformanceCritical"})," transitively calls a method annotated ",(0,r.jsx)(n.code,{children:"@Expensive"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_expensive_overrides_unannotated",children:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Overrides Unannotated" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@Expensive"})," overrides an un-annotated method."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_fragment_retains_view",children:"CHECKERS_FRAGMENT_RETAINS_VIEW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Fragment Retains View" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-fragment-retains-view",children:"fragment-retains-view"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error type is Android-specific. It fires when a ",(0,r.jsx)(n.code,{children:"Fragment"})," type fails to\nnullify one or more of its declared ",(0,r.jsx)(n.code,{children:"View"})," fields in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),". In\nperformance-sensitive applications, a ",(0,r.jsx)(n.code,{children:"Fragment"})," should initialize all ",(0,r.jsx)(n.code,{children:"View"}),"'s\nin ",(0,r.jsx)(n.code,{children:"onCreateView"})," and nullify them in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),". If a ",(0,r.jsx)(n.code,{children:"Fragment"})," is placed\non the back stack and fails to nullify a ",(0,r.jsx)(n.code,{children:"View"})," in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),", it will\nretain a useless reference to that ",(0,r.jsx)(n.code,{children:"View"})," that will not be cleaned up until the\n",(0,r.jsx)(n.code,{children:"Fragment"})," is resumed or destroyed."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Nullify the ",(0,r.jsx)(n.code,{children:"View"})," in question in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Compared To Null And Dereferenced" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A pointer that has both been compared to null, whcich suggests that it could be null, but has also been dereferenced without a null check."}),"\n",(0,r.jsx)(n.h2,{id:"config_impact",children:"CONFIG_IMPACT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Config Impact" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when an ",(0,r.jsx)(n.em,{children:"expensive"})," function is called without a ",(0,r.jsx)(n.em,{children:"config check"}),". The\n",(0,r.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,r.jsxs)(n.p,{children:["Similar to ",(0,r.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,r.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version1\nfoo();\nif (config_check){\n bar();\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"which is then modified to next"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version2\nfoo();\nif (config_check){\n bar();\n}\ngoo(); // added\n"})}),"\n",(0,r.jsxs)(n.p,{children:['the analysis would warn the developer that "',(0,r.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,r.jsx)(n.code,{children:"goo()"})," right after ",(0,r.jsx)(n.code,{children:"bar()"}),", then\nInfer wouldn't warn about it because it is already gated under the ",(0,r.jsx)(n.code,{children:"config_check"}),"."]}),"\n",(0,r.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,r.jsx)(n.code,{children:"version1"})," to ",(0,r.jsx)(n.code,{children:"version3"})," below by calling ",(0,r.jsx)(n.code,{children:"goo()"})," in ",(0,r.jsx)(n.code,{children:"foo()"}),","]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version3\nvoid foo(){\n // ....\n goo(); // added\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["then the analysis will report a ",(0,r.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue on the ungated call site of ",(0,r.jsx)(n.code,{children:"foo()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Currently, the analysis supports both Objective-C and Java but not C++."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"config_impact_strict",children:"CONFIG_IMPACT_STRICT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#ungated-code",children:"Ungated code"}),'. Reported as "Config Impact Strict" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.jsxs)(n.a,{href:"#config_impact",children:[(0,r.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue"]})," but the analysis reports ",(0,r.jsx)(n.strong,{children:"all"})," ungated\ncodes irrespective of whether they are expensive or not."]}),"\n",(0,r.jsx)(n.h2,{id:"config_usage",children:"CONFIG_USAGE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Config Usage" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when a ",(0,r.jsx)(n.em,{children:"config"})," value is used as branch condition in a function. The\n",(0,r.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,r.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'void foo() {\n if(config_check("my_new_feature")){ ... }\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:['then analysis would provide information that "the function ',(0,r.jsx)(n.code,{children:"foo"})," uses the config ",(0,r.jsx)(n.code,{children:"my_new_feature"}),' as\nbranch condition".']}),"\n",(0,r.jsx)(n.p,{children:"Note: This type of issue is only for providing semantic information, rather than warning or\nreporting actual problem."}),"\n",(0,r.jsx)(n.h2,{id:"constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Constant Address Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"#nullptr_dereference",children:(0,r.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," error type that is\nreported when the address is a constant other than zero."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, ",(0,r.jsx)(n.code,{children:"int *p = (int *) 123; *p = 42;"})," generates a ",(0,r.jsx)(n.code,{children:"CONSTANT_ADDRESS_DEREFERENCE"})," on ",(0,r.jsx)(n.code,{children:"*p = 42;"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["For more information see the ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:(0,r.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," issue type."]}),"\n",(0,r.jsx)(n.h2,{id:"constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Constant Address Dereference Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "C++ Reference Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.h2,{id:"cxx_string_captured_in_block",children:"CXX_STRING_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "C++ String Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,r.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" std::string fullName;\n const char* c = fullName.c_str();\n dispatch_async(dispatch_get_main_queue(), ^{\n const char* c1 = c;\n });\n"})}),"\n",(0,r.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,r.jsx)(n.h2,{id:"dangling_pointer_dereference",children:"DANGLING_POINTER_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Dangling Pointer Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.h2,{id:"data_flow_to_sink",children:"DATA_FLOW_TO_SINK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Data Flow to Sink" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A flow of data was detected to a sink."}),"\n",(0,r.jsx)(n.h2,{id:"deadlock",children:"DEADLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Deadlock" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsxs)(n.p,{children:["Old-style containers such as ",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Infer has support for detecting these deadlocks too."}),"\n",(0,r.jsxs)(n.p,{children:["To suppress reports of deadlocks in a method ",(0,r.jsx)(n.code,{children:"m()"})," use the\n",(0,r.jsx)(n.code,{children:'@SuppressLint("DEADLOCK")'})," annotation, as follows:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("DEADLOCK")\n public void m() {\n ...\n }\n'})}),"\n",(0,r.jsx)(n.h2,{id:"dead_store",children:"DEAD_STORE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Dead Store" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-liveness",children:"liveness"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"int i = 1; i = 2; return i;"}),")."]}),"\n",(0,r.jsx)(n.h2,{id:"divide_by_zero",children:"DIVIDE_BY_ZERO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Divide By Zero" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.h2,{id:"empty_vector_access",children:"EMPTY_VECTOR_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Empty Vector Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This error type is reported only in C++, in versions >= C++11."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"execution_time_complexity_increase",children:"EXECUTION_TIME_COMPLEXITY_INCREASE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-cost#examples-execution-cost",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"execution_time_complexity_increase_ui_thread",children:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of the procedure increases in degree ",(0,r.jsx)(n.strong,{children:"and"})," the procedure runs on the UI (main) thread."]}),"\n",(0,r.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,r.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,r.jsxs)(n.li,{children:["The method or its callees call a ",(0,r.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"execution_time_unreachable_at_exit",children:"EXECUTION_TIME_UNREACHABLE_AT_EXIT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Unreachable At Exit" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Examples:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"expensive_execution_time",children:"EXPENSIVE_EXECUTION_TIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Execution Time" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"enabled=true"})," in ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/base/costKind.ml#L55",children:"costKind.ml"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"For instance, a simple example where we report this issue is a function with linear cost:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"expensive_loop_invariant_call",children:"EXPENSIVE_LOOP_INVARIANT_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Loop Invariant Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["We report this issue type when a function is ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"})," analysis)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"guardedby_violation",children:"GUARDEDBY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "GuardedBy Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A field annotated with ",(0,r.jsx)(n.code,{children:"@GuardedBy"})," is being accessed by a call-chain that starts at a non-private method without synchronization."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Action: Protect the offending access by acquiring the lock indicated by the ",(0,r.jsx)(n.code,{children:"@GuardedBy(...)"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"impure_function",children:"IMPURE_FUNCTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Impure Function" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue type indicates impure functions. For instance, below functions would be marked as impure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Inefficient Keyset Iterator" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"inefficient-keyset-iterator"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue is raised when"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["iterating over a HashMap with ",(0,r.jsx)(n.code,{children:"keySet()"})," iterator"]}),"\n",(0,r.jsx)(n.li,{children:"looking up the key each time"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Instead, it is more efficient to iterate over the loop with ",(0,r.jsx)(n.code,{children:"entrySet"})," which returns key-vaue pairs and gets rid of the hashMap lookup."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"inferbo_alloc_is_big",children:"INFERBO_ALLOC_IS_BIG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Big" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is passed a large constant value (>=10^6). For example, ",(0,r.jsx)(n.code,{children:"int n = 1000000; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_BIG"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument or make sure it is really needed."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_is_negative",children:"INFERBO_ALLOC_IS_NEGATIVE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Negative" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is called with a negative size. For example, ",(0,r.jsx)(n.code,{children:"int n = 3 - 5; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_NEGATIVE"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_is_zero",children:"INFERBO_ALLOC_IS_ZERO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Zero" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is called with a zero size. For example, ",(0,r.jsx)(n.code,{children:"int n = 3 - 3; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_ZERO"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_may_be_big",children:"INFERBO_ALLOC_MAY_BE_BIG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc May Be Big" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," ",(0,r.jsx)(n.em,{children:"may"})," be called with a large value. For example, ",(0,r.jsx)(n.code,{children:"int n = b ? 3 : 1000000; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_BIG"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,r.jsx)(n.code,{children:"if (n < A_SMALL_NUMBER) { malloc(n); }"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_may_be_negative",children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc May Be Negative" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," ",(0,r.jsx)(n.em,{children:"may"})," be called with a negative value. For example, ",(0,r.jsx)(n.code,{children:"int n = b ? 3 : -5; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,r.jsx)(n.code,{children:"if (n > 0) { malloc(n); }"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"infinite_execution_time",children:"INFINITE_EXECUTION_TIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Infinite Execution Time" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"example-1-t-due-to-expressivity",children:"Example 1: T due to expressivity"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"example-2-t-due-to-unmodeled-calls",children:"Example 2: T due to unmodeled calls"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Here, Infer does not have any InferBo models for the range of values returned by ",(0,r.jsx)(n.code,{children:"String.toCharArray"}),", hence it cannot determine that we will be iterating over a char array in the size of ",(0,r.jsx)(n.code,{children:"input"})," string."]}),"\n",(0,r.jsxs)(n.p,{children:["To teach InferBo about such library calls, they should be semantically modeled in ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/bufferoverrun/bufferOverrunModels.ml",children:"InferBo"}),"."]}),"\n",(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L1" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is reported when integer overflow occurred by integer operations such as addition, subtraction,\nand multiplication. For example, ",(0,r.jsx)(n.code,{children:"int n = INT_MAX; int m = n + 3;"})," generates a INTEGER_OVERFLOW_L1\non ",(0,r.jsx)(n.code,{children:"n + 3"}),"."]}),"\n",(0,r.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,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,r.jsx)(n.em,{children:"must"})," be unsafe. For example,\n",(0,r.jsx)(n.code,{children:"[2147483647,2147483647] + [1,1]"})," in 32-bit signed integer type."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,r.jsx)(n.code,{children:"L1"}),", when it ",(0,r.jsx)(n.em,{children:"may"})," be unsafe. For example,\n",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L5"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.jsx)(n.h2,{id:"integer_overflow_l2",children:"INTEGER_OVERFLOW_L2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"integer_overflow_l5",children:"INTEGER_OVERFLOW_L5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"integer_overflow_u5",children:"INTEGER_OVERFLOW_U5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow U5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Interface Not Thread Safe" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error indicates that you have invoked an interface method not annotated\nwith ",(0,r.jsx)(n.code,{children:"@ThreadSafe"})," from a thread-safe context (e.g., code that uses locks or is\nmarked ",(0,r.jsx)(n.code,{children:"@ThreadSafe"}),"). The fix is to add the ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-racerd#interface-not-thread-safe",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"invalid_sil",children:"INVALID_SIL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Invalid Sil" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-sil-validation",children:"sil-validation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"invariant_call",children:"INVARIANT_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Invariant Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"We report this issue type when a function call is loop-invariant and hoistable, i.e."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"the function has no side side effects (pure)"}),"\n",(0,r.jsx)(n.li,{children:"has invariant arguments and result (i.e. have the same value in all loop iterations)"}),"\n",(0,r.jsx)(n.li,{children:"it is guaranteed to execute, i.e. it dominates all loop sources"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Ipc On Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A blocking ",(0,r.jsx)(n.code,{children:"Binder"})," IPC call occurs on the UI thread."]}),"\n",(0,r.jsx)(n.h2,{id:"lab_resource_leak",children:"LAB_RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Lab Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-resource-leak-lab",children:"resource-leak-lab"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Toy issue."}),"\n",(0,r.jsx)(n.h2,{id:"lineage_flow",children:"LINEAGE_FLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Lineage Flow" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-lineage",children:"lineage"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A Lineage taint flow has been detected from a source to a sink."}),"\n",(0,r.jsx)(n.h2,{id:"lockless_violation",children:"LOCKLESS_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Lockless Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method implements an interface signature annotated with ",(0,r.jsx)(n.code,{children:"@Lockless"})," but which transitively acquires a lock."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Lock Consistency Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This is an error reported on C++ and Objective C classes whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Some class method directly uses locking primitives (not transitively)."}),"\n",(0,r.jsxs)(n.li,{children:["It has a public method which writes to some member ",(0,r.jsx)(n.code,{children:"x"})," while holding a lock."]}),"\n",(0,r.jsxs)(n.li,{children:["It has a public method which reads ",(0,r.jsx)(n.code,{children:"x"})," without holding a lock."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The above may happen through a chain of calls. Above, ",(0,r.jsx)(n.code,{children:"x"})," may also be a\ncontainer (an array, a vector, etc)."]}),"\n",(0,r.jsx)(n.h3,{id:"fixing-lock-consistency-violation-reports",children:"Fixing Lock Consistency Violation reports"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Avoid the offending access (most often the read). Of course, this may not be\npossible."}),"\n",(0,r.jsx)(n.li,{children:"Use synchronization to protect the read, by using the same lock protecting the\ncorresponding write."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"memory_leak_c",children:"MEMORY_LEAK_C"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"memory-leak-in-c",children:"Memory leak in C"}),"\n",(0,r.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,r.jsxs)(n.p,{children:["In C, Infer reports memory leaks when objects are created with ",(0,r.jsx)(n.code,{children:"malloc"})," and not\nfreed. For example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-c",children:"-(void) memory_leak_bug {\n struct Person *p = malloc(sizeof(struct Person));\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"memory-leak-in-objective-c",children:"Memory leak in Objective-C"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"memory_leak_cpp",children:"MEMORY_LEAK_CPP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"})]}),"\n",(0,r.jsx)(n.h2,{id:"missing_required_prop",children:"MISSING_REQUIRED_PROP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Missing Required Prop" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-litho-required-props",children:"litho-required-props"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issues is reported when a required ",(0,r.jsx)(n.code,{children:"@Prop"})," is missing."]}),"\n",(0,r.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,r.jsxs)(n.p,{children:["Assume that the following Litho Component specification is defined as follows where ",(0,r.jsx)(n.code,{children:"prop1"})," is optional and ",(0,r.jsx)(n.code,{children:"prop2"})," is required."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.code,{children:"prop1"})," below), it is ok."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"MyComponent.create(c)\n .prop2(8)\n .build();\n"})}),"\n",(0,r.jsxs)(n.p,{children:["However, if we are missing a required prop, Infer gives an error below for the missing ",(0,r.jsx)(n.code,{children:"prop2"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .build();\n'})}),"\n",(0,r.jsx)(n.p,{children:"** Action **"}),"\n",(0,r.jsx)(n.p,{children:"There are two ways to fix this issue."}),"\n",(0,r.jsxs)(n.p,{children:["First, we could add the missing ",(0,r.jsx)(n.code,{children:"prop2"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["or alternatively, if the ",(0,r.jsx)(n.code,{children:"prop2"})," is not really required, we could change the component spec to reflect that:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Mixed Self WeakSelf" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports an issue when an Objective-C block captures both ",(0,r.jsx)(n.code,{children:"self"})," and ",(0,r.jsx)(n.code,{children:"weakSelf"}),", a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),".\nPossibly the developer meant to capture only ",(0,r.jsx)(n.code,{children:"weakSelf"})," to avoid a retain cycle, but made a typo and used ",(0,r.jsx)(n.code,{children:"self"}),"\ninstead of ",(0,r.jsx)(n.code,{children:"strongSelf"}),". In this case, this could cause a retain cycle."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),": Fixing the typo is generally the right course of action."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"modifies_immutable",children:"MODIFIES_IMMUTABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Modifies Immutable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue type indicates modifications to fields marked as @Immutable. For instance, below function ",(0,r.jsx)(n.code,{children:"mutateArray"})," would be marked as modifying immutable field ",(0,r.jsx)(n.code,{children:"testArray"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"multiple_weakself",children:"MULTIPLE_WEAKSELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Multiple WeakSelf Use" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when an Objective-C block uses ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),") more than once.\nThis could lead to unexpected behaviour. Even if ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"})," points to could be freed anytime."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"}),"\nOne should assign ",(0,r.jsx)(n.code,{children:"weakSelf"})," to a strong pointer first, and then\nuse it in the block."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Mutual Recursion Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A recursive call or mutually recursive call has been detected. This does ",(0,r.jsx)(n.em,{children:"not"})," mean that the program won't terminate, just that the code is recursive. You should double-check if the recursion is intended and if it can lead to non-termination or a stack overflow."]}),"\n",(0,r.jsx)(n.p,{children:"Example of recursive function:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-C",children:"int factorial(int x) {\n if (x > 0) {\n return x * factorial(x-1);\n } else {\n return 1;\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"nil_block_call",children:"NIL_BLOCK_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when one tries to call an Objective-C block that is ",(0,r.jsx)(n.code,{children:"nil"}),".\nThis causes a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Adding a check for ",(0,r.jsx)(n.code,{children:"nil"})," before calling the block, or making sure never to call the method ",(0,r.jsx)(n.code,{children:"foo:"})," with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_block_call",children:"NIL_BLOCK_CALL"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This checks reports when ",(0,r.jsx)(n.code,{children:"nil"})," is passed to collections in Objective-C such as arrays and dictionaries. This causes a crash."]}),"\n",(0,r.jsx)(n.h3,{id:"arrays",children:"Arrays"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"dictionaries",children:"Dictionaries"}),"\n",(0,r.jsxs)(n.p,{children:["Adding a ",(0,r.jsx)(n.code,{children:"nil"})," value in a dictionary causes a crash. If the concept of ",(0,r.jsx)(n.code,{children:"nil"})," is required, one can add\n",(0,r.jsx)(n.code,{children:"[NSNull null]"})," instead."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Retrieving or removing an object from a dictionary with a ",(0,r.jsx)(n.code,{children:"nil"})," key also causes a crash:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:' id key = nil;\n mDict[key] = @"somestring"; //crash\n\n [mDict removeObjectForKey:nil]; //crash\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["In all the cases above, when passing ",(0,r.jsx)(n.code,{children:"nil"})," causes a crash, the solutions are either making sure\nthat the object passed will never be ",(0,r.jsx)(n.code,{children:"nil"}),", or adding a check for ",(0,r.jsx)(n.code,{children:"nil"})," before calling those methods."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["In Objective-C, calling a method on ",(0,r.jsx)(n.code,{children:"nil"})," (or in Objective-C terms, sending a message to ",(0,r.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,r.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,r.jsx)(n.code,{children:"nil"})," causes undefined behaviour."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["To fix the above issue, we need to check if ",(0,r.jsx)(n.code,{children:"obj"})," is\nnot ",(0,r.jsx)(n.code,{children:"nil"})," before calling the ",(0,r.jsx)(n.code,{children:"returnsnonPOD"})," method:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching branch is found when evaluating the ",(0,r.jsx)(n.code,{children:"of"})," section of a ",(0,r.jsx)(n.code,{children:"try"})," expression. Corresponds to the ",(0,r.jsx)(n.code,{children:"{try_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching case clause in Erlang: Reports an error when none of the clauses of a ",(0,r.jsx)(n.code,{children:"case"})," match the expression. Corresponds to the ",(0,r.jsx)(n.code,{children:"{case_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n case X of\n [_|T] -> T\n end.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching else clause in Erlang: Reports an error when none of the clauses of an ",(0,r.jsx)(n.code,{children:"else"})," match the short-circuit result from ",(0,r.jsx)(n.code,{children:"maybe"})," body. Corresponds to the ",(0,r.jsx)(n.code,{children:"{else_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, here the ",(0,r.jsx)(n.code,{children:"1 ?= 2"})," expression does not match and short-circuits to ",(0,r.jsx)(n.code,{children:"2"}),", which does not match the single clause under ",(0,r.jsx)(n.code,{children:"else"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"else_clause_error() ->\n maybe\n 1 ?= 2\n else\n 1 -> ok\n end.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"function_clause"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"tail([_|Xs]) -> Xs.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"match"})," expression does not match the pattern on the left hand side. Corresponds to the ",(0,r.jsx)(n.code,{children:"{badmatch,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, ",(0,r.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,r.jsx)(n.h2,{id:"no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"if"})," expression evaluate to true. Corresponds to the ",(0,r.jsx)(n.code,{children:"if_clause"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"sign(0)"})," and the full definition of ",(0,r.jsx)(n.code,{children:"sign"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"sign(X) ->\n if\n X > 0 -> positive;\n X < 0 -> negative\n end.\n"})}),"\n",(0,r.jsx)(n.h2,{id:"no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nsstring_internal_ptr_captured_in_block",children:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "NSString Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,r.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" std::string fullName;\n const char* c = fullName.c_str();\n dispatch_async(dispatch_get_main_queue(), ^{\n const char* c1 = c;\n });\n"})}),"\n",(0,r.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-java",children:"Null dereference in Java"}),"\n",(0,r.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,r.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Change the code to ensure that ",(0,r.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Add a check that ",(0,r.jsx)(n.code,{children:"p"})," is not ",(0,r.jsx)(n.code,{children:"null"})," before dereferencing ",(0,r.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,r.jsx)(n.code,{children:"p"}),"\nis ",(0,r.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,r.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["The call ",(0,r.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,r.jsx)(n.code,{children:"null"}),": if ",(0,r.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,r.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,r.jsxs)(n.p,{children:["Facebook NOTE: ",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-c",children:"Null dereference in C"}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-objective-c",children:"Null dereference in Objective-C"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,r.jsx)(n.code,{children:"nil"})," check either for ",(0,r.jsx)(n.code,{children:"param"})," above or for ",(0,r.jsx)(n.code,{children:"d"}),", or making sure that ",(0,r.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Calling a ",(0,r.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Moreover, inserting ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-java-1",children:"Null dereference in Java"}),"\n",(0,r.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,r.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Change the code to ensure that ",(0,r.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Add a check that ",(0,r.jsx)(n.code,{children:"p"})," is not ",(0,r.jsx)(n.code,{children:"null"})," before dereferencing ",(0,r.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,r.jsx)(n.code,{children:"p"}),"\nis ",(0,r.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,r.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["The call ",(0,r.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,r.jsx)(n.code,{children:"null"}),": if ",(0,r.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,r.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,r.jsxs)(n.p,{children:["Facebook NOTE: ",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-c-1",children:"Null dereference in C"}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-objective-c-1",children:"Null dereference in Objective-C"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,r.jsx)(n.code,{children:"nil"})," check either for ",(0,r.jsx)(n.code,{children:"param"})," above or for ",(0,r.jsx)(n.code,{children:"d"}),", or making sure that ",(0,r.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Calling a ",(0,r.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Moreover, inserting ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"null_argument",children:"NULL_ARGUMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"null_argument_latent",children:"NULL_ARGUMENT_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#null_argument",children:"NULL_ARGUMENT"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"null_dereference",children:"NULL_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Optional Empty Access warnings are reported when we try to retrieve the value of a ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/folly/blob/master/folly/Optional.h",children:(0,r.jsx)(n.code,{children:"folly::Optional"})})," when it is empty (i.e. ",(0,r.jsx)(n.code,{children:"folly::none"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["In the following example we get a warning as ",(0,r.jsx)(n.code,{children:"int_opt"})," might be ",(0,r.jsx)(n.code,{children:"folly::none"})," and its value is being accessed:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["We do not get the warning anymore if we add a check whether ",(0,r.jsx)(n.code,{children:"int_opt"})," is not empty:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"premature_nil_termination_argument",children:"PREMATURE_NIL_TERMINATION_ARGUMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Premature Nil Termination Argument" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error type is reported in C and Objective-C. In many variadic methods,\n",(0,r.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,r.jsx)(n.code,{children:"nil"})," as well, Infer reports an error because that may\nlead to unexpected behavior."]}),"\n",(0,r.jsxs)(n.p,{children:["An example of such variadic methods is\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:' NSArray *foo = [NSArray arrayWithObjects: @"aaa", str, @"bbb", nil];\n'})}),"\n",(0,r.jsxs)(n.p,{children:["In this example, if ",(0,r.jsx)(n.code,{children:"str"})," is ",(0,r.jsx)(n.code,{children:"nil"})," then an array ",(0,r.jsx)(n.code,{children:'@[@"aaa"]'})," of size 1 will be\ncreated, and not an array ",(0,r.jsx)(n.code,{children:'@[@"aaa", str, @"bbb"]'})," of size 3 as expected."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Cannot Instantiate Abstract Class" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Instantiating an abstract class will lead to ",(0,r.jsx)(n.code,{children:"Cannot instantiate abstract class"})," error."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"abstract class AbstractClass1 {}\n\nclass ConcreteClass1 extends AbstractClass1 {}\n\npublic static function makeGeneric(classname $cls): void {\n new $cls();\n}\n\n<<__ConsistentConstruct>>\nabstract class AbstractClass2 {\n\n public static function makeStatic(): void {\n new static();\n }\n}\n\nclass ConcreteClass2 extends AbstractClass2 {}\n\npublic function badViaGeneric(): void {\n Main::makeGeneric(AbstractClass1::class); // ERROR!\n}\n\npublic function goodViaGeneric(): void {\n Main::makeGeneric(ConcreteClass1::class);\n}\n\npublic function badViaStatic(): void {\n AbstractClass2::makeStatic(); // ERROR!\n}\n\npublic function goodViaStatic(): void {\n ConcreteClass2::makeStatic();\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_const_refable",children:"PULSE_CONST_REFABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Const Refable Parameter" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"const&"})," so that no unnecessary copy is created at the callsite of the function."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dict Missing Key" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to warn\nreading a missing key of dictionary in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the dictionary ",(0,r.jsx)(n.code,{children:"$d"})," has no entry for ",(0,r.jsx)(n.code,{children:"bye"}),", so reading\n",(0,r.jsx)(n.code,{children:"$d['bye']"})," will throw the ",(0,r.jsx)(n.code,{children:"OutOfBoundsException"})," exception, which is usually unexpected from\ndevelopers. We can use a safer function ",(0,r.jsx)(n.code,{children:"idx"})," instead when keys of a dictionary is unclear."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dynamic Type Mismatch" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This error is reported in Hack. It fires when we detect an operation that is incompatible\nwith the dynamic type of its arguments."}),"\n",(0,r.jsxs)(n.p,{children:["For example, reading ",(0,r.jsx)(n.code,{children:"$x['key']"})," when ",(0,r.jsx)(n.code,{children:"$x"})," is a vector."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Read-only Shared Parameter" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"std::shared_ptr::get"})," at callsites."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"can be changed to"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Reference Stability" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["The family of maps ",(0,r.jsx)(n.code,{children:"folly::F14ValueMap"}),", ",(0,r.jsx)(n.code,{children:"folly::F14VectorMap"}),", and by extension\n",(0,r.jsx)(n.code,{children:"folly::F14FastMap"})," differs slightly from ",(0,r.jsx)(n.code,{children:"std::unordered_map"})," as it does not\nprovide reference stability. When the map resizes such as when ",(0,r.jsx)(n.code,{children:"reserve"})," is\ncalled or new elements are added, all existing references become invalid and\nshould not be used."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.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,r.jsx)(n.code,{children:"at"}),", ",(0,r.jsx)(n.code,{children:"find"}),", ",(0,r.jsx)(n.code,{children:"emplace"}),", or ",(0,r.jsx)(n.code,{children:"insert_or_assign"})," to increase code quality and\nsafety."]}),"\n",(0,r.jsx)(n.p,{children:"Examples:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#resource_leak",children:"RESOURCE_LEAK"})]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Transitive Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue tracks spurious accesses that are reachable from specific entry functions."}),"\n",(0,r.jsx)(n.p,{children:"Spurious accesses are specified as specific load/calls."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unawaited Awaitable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Awaitable"})," values created by calls to asynchronous methods should eventually be ",(0,r.jsx)(n.code,{children:"await"}),"ed along all codepaths (even if their value is unused). Hence the following is ",(0,r.jsx)(n.em,{children:"not"})," OK"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Failure to ",(0,r.jsx)(n.code,{children:"await"})," an ",(0,r.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,r.jsx)(n.code,{children:"T"})," and ",(0,r.jsx)(n.code,{children:"Awaitable"})," that may not be caught by the type-checker."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unfinished Builder" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Classes adhering to builder pattern are usually expected to call a finalizer function at some point to produce final result based on values that were passed to a builder itself. If finalizer function hasn't been called then builder's data won't be consumed in any meaningful way and will just be discarded."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"class MyBuilder {\n private int $a = 0;\n private int $b = 0;\n\n public function setA(int $a): MyBuilder {\n $this->a = $a;\n return $this;\n }\n\n public function setB(int $b): MyBuilder {\n $this->b = $b;\n return $this;\n }\n\n public function saveX(): Awaitable {\n // typically do something involving IO\n }\n}\n\nclass BuilderTester {\n public static function builderUserOK(): void {\n $b = new MyBuilder(0);\n $b->setA(42)->setB(97)->saveX();\n }\n\n public static function builderUserBad(): void {\n $b = new MyBuilder(0);\n $b->setA(42)->setB(97); // ERROR: saveX hasn't been called so the builder's data is discarded\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to detect the uninitialized abstract const value in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the ",(0,r.jsx)(n.code,{children:"FIELD"})," can be read by the static method ",(0,r.jsx)(n.code,{children:"get_field"}),"."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["It is problematic invoking ",(0,r.jsx)(n.code,{children:"static::FIELD"}),", since it may be resolved to a ",(0,r.jsx)(n.code,{children:"A::FIELD"})," access, if called from ",(0,r.jsx)(n.code,{children:"A::get_field()"}),". Because ",(0,r.jsx)(n.code,{children:"FIELD"})," is abstract in ",(0,r.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,r.jsxs)(n.li,{children:["In the ",(0,r.jsx)(n.code,{children:"B"})," class, ",(0,r.jsx)(n.code,{children:"FIELD"})," is initialized, thus invoking ",(0,r.jsx)(n.code,{children:"B::get_field"})," is safe."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Method" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_const",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_CONST"})}),", but it is to detect the uninitialized method call in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the static method ",(0,r.jsx)(n.code,{children:"foo"})," is declared only in the interface and the abstract class. Thus, calling the static method can introduce an unexpected exception or a fatal error, while the type checker does miss the issue."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"interface MyInterface {\n public static function foo(): string;\n}\n\nabstract class MyAbstractClass {\n public abstract static function foo(): string;\n}\n\nfunction interface_method_static_method_bad(): string {\n // Uncaught exception 'TypehintViolationException'\n $c = MyInterface::class;\n return $c::foo();\n}\n\nfunction abstract_class_static_method_bad(): string {\n // Fatal error: Cannot call abstract method\n $c = MyAbstractClass::class;\n return $c::foo();\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Uninitialized Value" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"The code uses a variable that has not been initialized, leading to unpredictable or unintended results."}),"\n",(0,r.jsx)(n.p,{children:"Using uninitialized values can lead to undefined behaviors possibly resulting in crashes, security failures and invalid results."}),"\n",(0,r.jsx)(n.p,{children:"This can easily be fixed by assigning all variables to an initial value when declaring them."}),"\n",(0,r.jsx)(n.p,{children:"This, for example, in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment Movable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"const &"}),"."]}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this case, when we call ",(0,r.jsx)(n.code,{children:"callee"}),", under the hood, a copy of the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is created to be passed to the function call. However, the copy might be unnecessary if"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"callee"})," doesn\u2019t modify its parameter \u2192 then we can change its type to ",(0,r.jsx)(n.code,{children:"const ExpensiveObject&"}),", getting rid of the copy at caller"]}),"\n",(0,r.jsxs)(n.li,{children:["even if ",(0,r.jsx)(n.code,{children:"callee"})," might modify the object, if the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is never used later on, we can get rid of the copy by moving it instead: ",(0,r.jsx)(n.code,{children:"callee(std::move(myExpensiveObj))"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The analysis is careful about suggesting moves blindly though: if the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is of type ",(0,r.jsx)(n.code,{children:"const & ExpensiveObject"})," then we also recommend that for move to work, const-reference needs to be removed."]}),"\n",(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Movable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy into a field where"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"the source is an rvalue-reference"}),"\n",(0,r.jsx)(n.li,{children:"the source is not modified before it goes out of scope or is destroyed."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note that the copy can be modified since it has the ownership of the object."}),"\n",(0,r.jsx)(n.p,{children:"Fix: Rather than the copying into the field, the source should be moved into it."}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary copy of an object via ",(0,r.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,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Return" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.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,r.jsx)(n.code,{children:"std::move"})," to avoid the copy."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment into Thrift" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),", but is\nreported when copied into thrift fields."]}),"\n",(0,r.jsx)(n.h2,{id:"pure_function",children:"PURE_FUNCTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Pure Function" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-purity",children:"purity"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue type indicates pure functions. For instance, below functions would be marked as pure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"However, the following ones would not be pure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Regex Op On Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A potentially costly operation on a regular expression occurs on the UI thread."}),"\n",(0,r.jsx)(n.h2,{id:"resource_leak",children:"RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"resource-leak-in-c",children:"Resource leak in C"}),"\n",(0,r.jsx)(n.p,{children:"This is an example of a resource leak in C code:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"resource-leak-in-java",children:"Resource leak in Java"}),"\n",(0,r.jsx)(n.p,{children:"For the remaining of this section, we will consider examples of resource leaks\nin Java code."}),"\n",(0,r.jsxs)(n.p,{children:["TIP: A common source of bugs is ",(0,r.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,r.jsx)(n.h3,{id:"basics-and-standard-idiom",children:"Basics and Standard Idiom"}),"\n",(0,r.jsxs)(n.p,{children:["Some objects in Java, the ",(0,r.jsx)("i",{children:"resources"}),", are supposed to be closed when you\nstop using them, and failure to close is a ",(0,r.jsx)("i",{children:"resource leak"}),". Resources\ninclude input streams, output streams, readers, writers, sockets, http\nconnections, cursors, and json parsers."]}),"\n",(0,r.jsx)(n.p,{children:"The standard idiom is"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"or more for example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"where an exception in fos.write will cause execution to skip past the close()\nstatement."}),"\n",(0,r.jsx)(n.h4,{id:"multiple-resources-bugs",children:"Multiple Resources Bugs"}),"\n",(0,r.jsx)(n.p,{children:"We can deal with multiple resources correctly and simply just by nesting the\nstandard idiom."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Bugs often occur when using multiple resources in other ways because of\nexceptions in close() methods. For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.p,{children:"Another way, besides the standard idiom, to deal with this problem is to swallow\nexceptions."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.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,r.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,r.jsx)(n.h3,{id:"nested_allocations",children:"Nested_Allocations"}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.p,{children:"Here are resources that can throw exceptions i their constructor(s)."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"ObjectInputStream , ObjectOutputStream, PipedInputStream, PipedOutputStream,\nPipedReader, PipedWriter, JarInputStream, JarOutputStream, GZIPInputStream,\nGZIPOutputStream , ZipFile all throw IOException"}),"\n",(0,r.jsx)(n.li,{children:"PrintStream throws UnsupportedEncodingException"}),"\n"]}),"\n",(0,r.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,r.jsx)(n.h3,{id:"allocation-of-jsonparser-and-cursor-resources",children:"Allocation of JSonParser and Cursor resources"}),"\n",(0,r.jsx)(n.p,{children:'Some resources are created inside libraries instead of by "new".'}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.h3,{id:"escaping-resources-and-exceptions",children:"Escaping resources and exceptions"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this case it is intended that an object that wraps ",(0,r.jsx)(n.code,{children:"stream"})," is passed to the\ncaller of ",(0,r.jsx)(n.code,{children:"createAttachment"}),". You should certainly not close stream here,\nbecause it is being passed to the outside."]}),"\n",(0,r.jsx)(n.p,{children:"But for escaping resources like this you still need to be careful of exceptions.\nFor example, in"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.h3,{id:"java-7s-try-with-resources",children:"Java 7's try-with-resources"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"(For use with Java 7 only)"})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"All the complicated exceptional cases above are (apparently) covered by this\nconstruct, and the result is much simpler."}),"\n",(0,r.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,r.jsxs)(n.p,{children:["If try-with-resources is so great you should ",(0,r.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,r.jsx)(n.h2,{id:"retain_cycle",children:"RETAIN_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle No Weak Info" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"scope_leakage",children:"SCOPE_LEAKAGE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Scope Leakage" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-scope-leakage",children:"scope-leakage"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"A configuration is used to list the set of scopes and the must-not-hold relation."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Here is a more detailed description of the analysis."}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.h2,{id:"self_in_block_passed_to_init",children:"SELF_IN_BLOCK_PASSED_TO_INIT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Self In Block Passed To Init" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when ",(0,r.jsx)(n.code,{children:"self"})," is captured in a block that is passed to an initialiser method. That\ncould cause retain cycles if the initialiser code retains the block."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" [obj initWithHandler:^() {\n [self foo];\n ...\n }];\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Instead it's better to use the ",(0,r.jsx)(n.code,{children:"weakSelf"}),"/",(0,r.jsx)(n.code,{children:"strongSelf"})," pattern."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n [obj initWithHandler:^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n }\n ...\n }];\n"})}),"\n",(0,r.jsx)(n.h2,{id:"sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Sensitive Data Flow" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A flow of sensitive data was detected from a source."}),"\n",(0,r.jsx)(n.h2,{id:"stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Stack Variable Address Escape" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example, directly returning a pointer to a local variable:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"starvation",children:"STARVATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "UI Thread Starvation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,r.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,r.jsxs)(n.li,{children:["The method or its callees call a ",(0,r.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The issue is reported when a method deemed to run on the UI thread"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Makes a method call which may block."}),"\n",(0,r.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,r.jsx)(n.p,{children:"Calls that may block are considered:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Certain I/O calls."}),"\n",(0,r.jsxs)(n.li,{children:["Two way ",(0,r.jsx)(n.code,{children:"Binder.transact"})," calls."]}),"\n",(0,r.jsx)(n.li,{children:"Certain OS calls."}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"Future"})," or ",(0,r.jsx)(n.code,{children:"AsyncTask"})," calls to ",(0,r.jsx)(n.code,{children:"get"})," without timeouts, or with too large\ntimeouts."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["To suppress starvation reports in a method ",(0,r.jsx)(n.code,{children:"m()"})," use the\n",(0,r.jsx)(n.code,{children:'@SuppressLint("STARVATION")'})," annotation, as follows:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("STARVATION")\n public void m() {\n ...\n }\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To signal to Infer that a method does not perform any blocking calls, despite\nappearences, you can use the ",(0,r.jsx)(n.code,{children:"@NonBlocking"})," annotation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["This instructs Infer to filter out any potentially blocking calls in ",(0,r.jsx)(n.code,{children:"m()"}),"\n(also, transitively), and thus any other method can expect no starvation reports\ndue to a call to ",(0,r.jsx)(n.code,{children:"m()"}),". You will need to set up your class path appropriately to\ninclude the JAR files in ",(0,r.jsx)(n.code,{children:"infer/annotations"})," for this annotation to work."]}),"\n",(0,r.jsx)(n.h2,{id:"static_constructor_stall",children:"STATIC_CONSTRUCTOR_STALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Static Constructor Stall" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-static-constructor-stall-checker",children:"static-constructor-stall-checker"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Calling certain methods, for instance dispatch_once, during the static initialization of objects is risky. It could cause deadlocks, because other objects might not have been initialized yet."}),"\n",(0,r.jsx)(n.h2,{id:"static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Static Initialization Order Fiasco" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-siof",children:"siof"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error is reported in C++. It fires when the initialization of a static\nvariable ",(0,r.jsx)(n.code,{children:"A"}),", accesses a static variable ",(0,r.jsx)(n.code,{children:"B"})," from another translation unit\n(usually another ",(0,r.jsx)(n.code,{children:".cpp"})," file). There are no guarantees whether ",(0,r.jsx)(n.code,{children:"B"})," has been\nalready initialized or not at that point."]}),"\n",(0,r.jsxs)(n.p,{children:["For more technical definition and techniques to avoid/remediate, see the\n",(0,r.jsx)(n.a,{href:"https://isocpp.org/wiki/faq/ctors#static-init-order",children:"FAQ"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"strict_mode_violation",children:"STRICT_MODE_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Strict Mode Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Android has a feature called\n",(0,r.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,r.jsx)(n.code,{children:"--starvation"})," analysis) has the\nability to statically detect such violations."]}),"\n",(0,r.jsxs)(n.p,{children:["To suppress this warning, it's enough to annotate the offending method with\n",(0,r.jsx)(n.code,{children:'@SuppressLint("STRICT_MODE_VIOLATION")'}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "StrongSelf Not Checked" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This checks reports a potential issue when a block captures ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),"),\nthen one assigns this pointer to a local variable ",(0,r.jsx)(n.code,{children:"strongSelf"})," inside the block and uses this variable\nwithout checking first whether it is ",(0,r.jsx)(n.code,{children:"nil"}),". The problem here is that the weak pointer could be ",(0,r.jsx)(n.code,{children:"nil"})," at\nthe time when the block is executed. So, the correct usage is to first check whether ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a valid\npointer, and then use it."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"}),"\nAdd a check for ",(0,r.jsx)(n.code,{children:"nil"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"taint_error",children:"TAINT_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Taint Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A taint flow was detected from a source to a sink"}),"\n",(0,r.jsx)(n.h2,{id:"thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Thread Safety Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"RacerD page"})," for more in-depth information and\nexamples."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-what-is-a-data-race",children:"Thread-safety: What is a data race"}),"\n",(0,r.jsx)(n.p,{children:"Here a data race is a pair of accesses to the same member field such that:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"at least one is a write, and,"}),"\n",(0,r.jsx)(n.li,{children:"at least one occurs without any lock synchronization, and,"}),"\n",(0,r.jsx)(n.li,{children:"the two accesses occur on threads (if known) which can run in parallel."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-potential-fixes",children:"Thread-safety: Potential fixes"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Synchronizing the accesses (using the ",(0,r.jsx)(n.code,{children:"synchronized"})," keyword, thread-exclusion\nsuch as atomic objects, ",(0,r.jsx)(n.code,{children:"volatile"})," etc)."]}),"\n",(0,r.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,r.jsxs)(n.li,{children:["Putting the two accesses on the same thread, e.g., by using ",(0,r.jsx)(n.code,{children:"@MainThread"})," or\n",(0,r.jsx)(n.code,{children:"@ThreadConfined"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-conditions-checked-before-reporting",children:"Thread-safety: Conditions checked before reporting"}),"\n",(0,r.jsxs)(n.p,{children:["The class and method are not marked ",(0,r.jsx)(n.code,{children:"@ThreadSafe(enableChecks = false)"}),", and,"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method is declared ",(0,r.jsx)(n.code,{children:"synchronized"}),", or employs (non-transitively) locking,\nor,"]}),"\n",(0,r.jsxs)(n.li,{children:["The class is not marked ",(0,r.jsx)(n.code,{children:"@NotThreadSafe"}),", and,","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The class/method is marked ",(0,r.jsx)(n.code,{children:"@ThreadSafe,"})," or one of the configured synonyms\nin ",(0,r.jsx)(n.code,{children:".inferconfig"}),", or,"]}),"\n",(0,r.jsx)(n.li,{children:"A parent class, or an override method are marked with the above annotations."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["NB currently RacerD ",(0,r.jsxs)(n.strong,{children:["does not take into account ",(0,r.jsx)(n.code,{children:"@GuardedBy"})]}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-thread-annotations-recognized-by-racerd",children:"Thread-safety: Thread annotations recognized by RacerD"}),"\n",(0,r.jsxs)(n.p,{children:["These class and method annotations imply the method is on the main thread:\n",(0,r.jsx)(n.code,{children:"@MainThread"}),", ",(0,r.jsx)(n.code,{children:"@UiThread"})]}),"\n",(0,r.jsxs)(n.p,{children:["These method annotations imply the method is on the main thread: ",(0,r.jsx)(n.code,{children:"@OnBind"}),",\n",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnMount"}),", ",(0,r.jsx)(n.code,{children:"@OnUnbind"}),", ",(0,r.jsx)(n.code,{children:"@OnUnmount"})]}),"\n",(0,r.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,r.jsxs)(n.p,{children:["In addition to these, RacerD recognizes many lifecycle methods as necessarily\nrunning on the main thread, eg ",(0,r.jsx)(n.code,{children:"Fragment.onCreate"})," etc."]}),"\n",(0,r.jsxs)(n.p,{children:["Finally, the thread status of being on the main thread propagates backwards\nthrough the call graph (ie if ",(0,r.jsx)(n.code,{children:"foo"})," calls ",(0,r.jsx)(n.code,{children:"bar"})," and ",(0,r.jsx)(n.code,{children:"bar"})," is marked ",(0,r.jsx)(n.code,{children:"@UiThtread"}),"\nthen ",(0,r.jsx)(n.code,{children:"foo"})," is automatically considered on the main thread too). Calling\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),", ",(0,r.jsx)(n.code,{children:"assertOnUiThread"}),", ",(0,r.jsx)(n.code,{children:"checkOnMainThread"})," has the same effect."]}),"\n",(0,r.jsxs)(n.p,{children:["NB RacerD currently ",(0,r.jsxs)(n.strong,{children:["does not recognize ",(0,r.jsx)(n.code,{children:"@WorkerThread"}),", ",(0,r.jsx)(n.code,{children:"@BinderThread"})," or\n",(0,r.jsx)(n.code,{children:"@AnyThread"})]}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-other-annotations-and-what-they-do",children:"Thread-safety: Other annotations and what they do"}),"\n",(0,r.jsxs)(n.p,{children:["These annotations can be found at ",(0,r.jsx)(n.code,{children:"com.facebook.infer.annotation.*"}),"."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@Functional"})," This is a method annotation indicating the method always returns\nthe same value. When a method ",(0,r.jsx)(n.code,{children:"foo"})," is annotated ",(0,r.jsx)(n.code,{children:"@Functional"}),", RacerD will\nignore any writes of the return value of ",(0,r.jsx)(n.code,{children:"foo"}),". For example, in\n",(0,r.jsx)(n.code,{children:"this.x = foo()"}),", the write to ",(0,r.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,r.jsx)(n.code,{children:"this.x"})," is benign, if that is the only write."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@ThreadConfined"})," This is a class/method/field annotation which takes a single\nparameter which can be ",(0,r.jsx)(n.code,{children:"UI"}),", ",(0,r.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,r.jsx)(n.code,{children:"@ThreadConfined(UI)"})," is equivalent to ",(0,r.jsx)(n.code,{children:"@UiThread"}),", and ",(0,r.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,r.jsx)(n.code,{children:"UI"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@VisibleForTesting"})," A method annotation making Infer consider the method as\neffectively ",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.jsx)(n.h2,{id:"topl_error",children:"TOPL_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"This indicates that the code has a user-defined undesired behavior."}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"/docs/next/checker-topl#what-is-it",children:"Topl"})," for an example"]}),"\n",(0,r.jsx)(n.h2,{id:"topl_error_latent",children:"TOPL_ERROR_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#topl_error",children:"TOPL_ERROR"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_delete",children:"USE_AFTER_DELETE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,r.jsx)(n.code,{children:"delete"})," in C++ is dereferenced."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_delete",children:"USE_AFTER_DELETE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_free",children:"USE_AFTER_FREE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,r.jsx)(n.code,{children:"free"})," in C is dereferenced."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_free_latent",children:"USE_AFTER_FREE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_free",children:"USE_AFTER_FREE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_lifetime",children:"USE_AFTER_LIFETIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_lifetime",children:"USE_AFTER_LIFETIME"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"vector_invalidation",children:"VECTOR_INVALIDATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address pointing into a C++ ",(0,r.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,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'void deref_vector_element_after_push_back_bad(std::vector& vec) {\n int* elt = &vec[1];\n int* y = elt;\n vec.push_back(42); // if the array backing the vector was full already, this\n // will re-allocate it and copy the previous contents\n // into the new array, then delete the previous array\n std::cout << *y << "\\n"; // bad: y might be invalid\n}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#vector_invalidation",children:"VECTOR_INVALIDATION"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"weak_self_in_no_escape_block",children:"WEAK_SELF_IN_NO_ESCAPE_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Weak Self In No Escape Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.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,r.jsx)(n.code,{children:"NS_NOESCAPE"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:['The issue here is that, because the block is "no escaping", there is no need to use\n',(0,r.jsx)(n.code,{children:"weakSelf"})," and ",(0,r.jsx)(n.code,{children:"strongSelf"})," but we can just use ",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Replace ",(0,r.jsx)(n.code,{children:"weakSelf"})," with ",(0,r.jsx)(n.code,{children:"self"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" [self foo:^() {\n [self bar];\n }];\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>l});var r=s(6540);const i={},t=r.createContext(i);function a(e){const n=r.useContext(t);return r.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(i):e.components||i:a(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/c359af60.87765c92.js b/assets/js/c359af60.87765c92.js
new file mode 100644
index 00000000000..6b7908d2416
--- /dev/null
+++ b/assets/js/c359af60.87765c92.js
@@ -0,0 +1 @@
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2316],{28:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>o});var r=s(4848),i=s(8453);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 categories of issue types",permalink:"/docs/next/all-categories"},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_GENERATOR",id:"bad_generator",level:2},{value:"BAD_GENERATOR_LATENT",id:"bad_generator_latent",level:2},{value:"BAD_KEY",id:"bad_key",level:2},{value:"BAD_KEY_LATENT",id:"bad_key_latent",level:2},{value:"BAD_MAP",id:"bad_map",level:2},{value:"BAD_MAP_LATENT",id:"bad_map_latent",level:2},{value:"BAD_RECORD",id:"bad_record",level:2},{value:"BAD_RECORD_LATENT",id:"bad_record_latent",level:2},{value:"BAD_RETURN",id:"bad_return",level:2},{value:"BAD_RETURN_LATENT",id:"bad_return_latent",level:2},{value:"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:"COMPARED_TO_NULL_AND_DEREFERENCED",id:"compared_to_null_and_dereferenced",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:"CXX_REF_CAPTURED_IN_BLOCK",id:"cxx_ref_captured_in_block",level:2},{value:"CXX_STRING_CAPTURED_IN_BLOCK",id:"cxx_string_captured_in_block",level:2},{value:"DANGLING_POINTER_DEREFERENCE",id:"dangling_pointer_dereference",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:"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:"INFINITE_RECURSION",id:"infinite_recursion",level:2},{value:"INTEGER_OVERFLOW_L1",id:"integer_overflow_l1",level:2},{value:"INTEGER_OVERFLOW_L2",id:"integer_overflow_l2",level:2},{value:"INTEGER_OVERFLOW_L5",id:"integer_overflow_l5",level:2},{value:"INTEGER_OVERFLOW_U5",id:"integer_overflow_u5",level:2},{value:"INTERFACE_NOT_THREAD_SAFE",id:"interface_not_thread_safe",level:2},{value:"INVALID_SIL",id:"invalid_sil",level:2},{value:"INVARIANT_CALL",id:"invariant_call",level:2},{value:"IPC_ON_UI_THREAD",id:"ipc_on_ui_thread",level:2},{value:"LAB_RESOURCE_LEAK",id:"lab_resource_leak",level:2},{value:"LINEAGE_FLOW",id:"lineage_flow",level:2},{value:"LOCKLESS_VIOLATION",id:"lockless_violation",level:2},{value:"LOCK_CONSISTENCY_VIOLATION",id:"lock_consistency_violation",level:2},{value:"Fixing Lock Consistency Violation reports",id:"fixing-lock-consistency-violation-reports",level:3},{value:"LOCK_ON_UI_THREAD",id:"lock_on_ui_thread",level:2},{value:"MEMORY_LEAK_C",id:"memory_leak_c",level:2},{value:"Memory leak in C",id:"memory-leak-in-c",level:3},{value:"Memory leak in Objective-C",id:"memory-leak-in-objective-c",level:3},{value:"MEMORY_LEAK_CPP",id:"memory_leak_cpp",level:2},{value:"MISSING_REQUIRED_PROP",id:"missing_required_prop",level:2},{value:"Examples",id:"examples",level:2},{value:"MIXED_SELF_WEAKSELF",id:"mixed_self_weakself",level:2},{value:"MODIFIES_IMMUTABLE",id:"modifies_immutable",level:2},{value:"MULTIPLE_WEAKSELF",id:"multiple_weakself",level:2},{value:"MUTUAL_RECURSION_CYCLE",id:"mutual_recursion_cycle",level:2},{value:"NIL_BLOCK_CALL",id:"nil_block_call",level:2},{value:"NIL_BLOCK_CALL_LATENT",id:"nil_block_call_latent",level:2},{value:"NIL_INSERTION_INTO_COLLECTION",id:"nil_insertion_into_collection",level:2},{value:"Arrays",id:"arrays",level:3},{value:"Dictionaries",id:"dictionaries",level:3},{value:"NIL_INSERTION_INTO_COLLECTION_LATENT",id:"nil_insertion_into_collection_latent",level:2},{value:"NIL_MESSAGING_TO_NON_POD",id:"nil_messaging_to_non_pod",level:2},{value:"NIL_MESSAGING_TO_NON_POD_LATENT",id:"nil_messaging_to_non_pod_latent",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY",id:"no_matching_branch_in_try",level:2},{value:"NO_MATCHING_BRANCH_IN_TRY_LATENT",id:"no_matching_branch_in_try_latent",level:2},{value:"NO_MATCHING_CASE_CLAUSE",id:"no_matching_case_clause",level:2},{value:"NO_MATCHING_CASE_CLAUSE_LATENT",id:"no_matching_case_clause_latent",level:2},{value:"NO_MATCHING_ELSE_CLAUSE",id:"no_matching_else_clause",level:2},{value:"NO_MATCHING_ELSE_CLAUSE_LATENT",id:"no_matching_else_clause_latent",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE",id:"no_matching_function_clause",level:2},{value:"NO_MATCHING_FUNCTION_CLAUSE_LATENT",id:"no_matching_function_clause_latent",level:2},{value:"NO_MATCH_OF_RHS",id:"no_match_of_rhs",level:2},{value:"NO_MATCH_OF_RHS_LATENT",id:"no_match_of_rhs_latent",level:2},{value:"NO_TRUE_BRANCH_IN_IF",id:"no_true_branch_in_if",level:2},{value:"NO_TRUE_BRANCH_IN_IF_LATENT",id:"no_true_branch_in_if_latent",level:2},{value:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK",id:"nsstring_internal_ptr_captured_in_block",level:2},{value:"NULLPTR_DEREFERENCE",id:"nullptr_dereference",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java",level:3},{value:"Null dereference in C",id:"null-dereference-in-c",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS",id:"nullptr_dereference_in_nullsafe_class",level:2},{value:"Null dereference in Java",id:"null-dereference-in-java-1",level:3},{value:"Null dereference in C",id:"null-dereference-in-c-1",level:3},{value:"Null dereference in Objective-C",id:"null-dereference-in-objective-c-1",level:3},{value:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT",id:"nullptr_dereference_in_nullsafe_class_latent",level:2},{value:"NULLPTR_DEREFERENCE_LATENT",id:"nullptr_dereference_latent",level:2},{value:"NULL_ARGUMENT",id:"null_argument",level:2},{value:"NULL_ARGUMENT_LATENT",id:"null_argument_latent",level:2},{value:"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_CANNOT_INSTANTIATE_ABSTRACT_CLASS",id:"pulse_cannot_instantiate_abstract_class",level:2},{value:"PULSE_CONST_REFABLE",id:"pulse_const_refable",level:2},{value:"PULSE_DICT_MISSING_KEY",id:"pulse_dict_missing_key",level:2},{value:"PULSE_DYNAMIC_TYPE_MISMATCH",id:"pulse_dynamic_type_mismatch",level:2},{value:"PULSE_READONLY_SHARED_PTR_PARAM",id:"pulse_readonly_shared_ptr_param",level:2},{value:"PULSE_REFERENCE_STABILITY",id:"pulse_reference_stability",level:2},{value:"PULSE_RESOURCE_LEAK",id:"pulse_resource_leak",level:2},{value:"PULSE_TRANSITIVE_ACCESS",id:"pulse_transitive_access",level:2},{value:"PULSE_UNAWAITED_AWAITABLE",id:"pulse_unawaited_awaitable",level:2},{value:"PULSE_UNFINISHED_BUILDER",id:"pulse_unfinished_builder",level:2},{value:"PULSE_UNINITIALIZED_CONST",id:"pulse_uninitialized_const",level:2},{value:"PULSE_UNINITIALIZED_METHOD",id:"pulse_uninitialized_method",level:2},{value:"PULSE_UNINITIALIZED_VALUE",id:"pulse_uninitialized_value",level:2},{value:"PULSE_UNNECESSARY_COPY",id:"pulse_unnecessary_copy",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT",id:"pulse_unnecessary_copy_assignment",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST",id:"pulse_unnecessary_copy_assignment_const",level:2},{value:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE",id:"pulse_unnecessary_copy_assignment_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE",id:"pulse_unnecessary_copy_intermediate",level:2},{value:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST",id:"pulse_unnecessary_copy_intermediate_const",level:2},{value:"PULSE_UNNECESSARY_COPY_MOVABLE",id:"pulse_unnecessary_copy_movable",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL",id:"pulse_unnecessary_copy_optional",level:2},{value:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST",id:"pulse_unnecessary_copy_optional_const",level:2},{value:"PULSE_UNNECESSARY_COPY_RETURN",id:"pulse_unnecessary_copy_return",level:2},{value:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT",id:"pulse_unnecessary_copy_thrift_assignment",level:2},{value:"PURE_FUNCTION",id:"pure_function",level:2},{value:"REGEX_OP_ON_UI_THREAD",id:"regex_op_on_ui_thread",level:2},{value:"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:"RETAIN_CYCLE_NO_WEAK_INFO",id:"retain_cycle_no_weak_info",level:2},{value:"SCOPE_LEAKAGE",id:"scope_leakage",level:2},{value:"SELF_IN_BLOCK_PASSED_TO_INIT",id:"self_in_block_passed_to_init",level:2},{value:"SENSITIVE_DATA_FLOW",id:"sensitive_data_flow",level:2},{value:"STACK_VARIABLE_ADDRESS_ESCAPE",id:"stack_variable_address_escape",level:2},{value:"STARVATION",id:"starvation",level:2},{value:"STATIC_CONSTRUCTOR_STALL",id:"static_constructor_stall",level:2},{value:"STATIC_INITIALIZATION_ORDER_FIASCO",id:"static_initialization_order_fiasco",level:2},{value:"STRICT_MODE_VIOLATION",id:"strict_mode_violation",level:2},{value:"STRONG_SELF_NOT_CHECKED",id:"strong_self_not_checked",level:2},{value:"TAINT_ERROR",id:"taint_error",level:2},{value:"THREAD_SAFETY_VIOLATION",id:"thread_safety_violation",level:2},{value:"Thread-safety: What is a data race",id:"thread-safety-what-is-a-data-race",level:3},{value:"Thread-safety: Potential fixes",id:"thread-safety-potential-fixes",level:3},{value:"Thread-safety: Conditions checked before reporting",id:"thread-safety-conditions-checked-before-reporting",level:3},{value:"Thread-safety: Thread annotations recognized by RacerD",id:"thread-safety-thread-annotations-recognized-by-racerd",level:3},{value:"Thread-safety: Other annotations and what they do",id:"thread-safety-other-annotations-and-what-they-do",level:3},{value:"TOPL_ERROR",id:"topl_error",level:2},{value:"TOPL_ERROR_LATENT",id:"topl_error_latent",level:2},{value:"USE_AFTER_DELETE",id:"use_after_delete",level:2},{value:"USE_AFTER_DELETE_LATENT",id:"use_after_delete_latent",level:2},{value:"USE_AFTER_FREE",id:"use_after_free",level:2},{value:"USE_AFTER_FREE_LATENT",id:"use_after_free_latent",level:2},{value:"USE_AFTER_LIFETIME",id:"use_after_lifetime",level:2},{value:"USE_AFTER_LIFETIME_LATENT",id:"use_after_lifetime_latent",level:2},{value:"VECTOR_INVALIDATION",id:"vector_invalidation",level:2},{value:"VECTOR_INVALIDATION_LATENT",id:"vector_invalidation_latent",level:2},{value:"WEAK_SELF_IN_NO_ESCAPE_BLOCK",id:"weak_self_in_no_escape_block",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"Here is an overview of the issue types currently reported by Infer."}),"\n",(0,r.jsx)(n.h2,{id:"arbitrary_code_execution_under_lock",children:"ARBITRARY_CODE_EXECUTION_UNDER_LOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Arbitrary Code Execution Under lock" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"bad_arg",children:"BAD_ARG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"badarg"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to concatenate the number ",(0,r.jsx)(n.code,{children:"3"})," with the list ",(0,r.jsx)(n.code,{children:"[1,2]"})," gives ",(0,r.jsx)(n.code,{children:"badarg"})," error because ",(0,r.jsx)(n.code,{children:"3"})," is not a list."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n 3 ++ [1,2]. // badarg error\n"})}),"\n",(0,r.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,r.jsx)(n.code,{children:"3"})," raises no error in Erlang."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"g() ->\n [1,2] ++ 3. // no error. Result: [1,2|3]\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_arg_latent",children:"BAD_ARG_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Arg Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_arg",children:"BAD_ARG"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_generator",children:"BAD_GENERATOR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Bad generator in Erlang: Reports an error when a wrong type is used in a generator. Corresponds to the ",(0,r.jsx)(n.code,{children:"bad_generator"})," error in the Erlang runtime."]}),"\n",(0,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"list_instead_of_map() ->\n M = [],\n [{K, V} || K := V <- M]\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_generator_latent",children:"BAD_GENERATOR_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Generator Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_generator",children:"BAD_GENERATOR"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_key",children:"BAD_KEY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badkey,K}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to update the key ",(0,r.jsx)(n.code,{children:"2"})," in ",(0,r.jsx)(n.code,{children:"M"})," gives ",(0,r.jsx)(n.code,{children:"{badkey,2}"})," error because ",(0,r.jsx)(n.code,{children:"2"})," is not present as a key in ",(0,r.jsx)(n.code,{children:"M"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n M = #{},\n M#{2 := 3}.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"bad_key_latent",children:"BAD_KEY_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Key Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_key",children:"BAD_KEY"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_map",children:"BAD_MAP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badmap,...}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, trying to update ",(0,r.jsx)(n.code,{children:"L"})," as if it was a map gives ",(0,r.jsx)(n.code,{children:"{badmap,[1,2,3]}"})," error because ",(0,r.jsx)(n.code,{children:"L"})," is actually a list (",(0,r.jsx)(n.code,{children:"[1,2,3]"}),")."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"f() ->\n L = [1,2,3],\n L#{1 => 2}.\n"})}),"\n",(0,r.jsx)(n.h2,{id:"bad_map_latent",children:"BAD_MAP_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Map Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_map",children:"BAD_MAP"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_record",children:"BAD_RECORD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"{badrecord,Name}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, accessing ",(0,r.jsx)(n.code,{children:"R"})," as a ",(0,r.jsx)(n.code,{children:"person"})," record gives ",(0,r.jsx)(n.code,{children:"{badrecord,person}"})," error because ",(0,r.jsx)(n.code,{children:"R"})," is ",(0,r.jsx)(n.code,{children:"rabbit"})," (even though both share the ",(0,r.jsx)(n.code,{children:"name"})," field)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"bad_record_latent",children:"BAD_RECORD_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Bad Record Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_record",children:"BAD_RECORD"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_return",children:"BAD_RETURN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Bad Return" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example, this function returns an integer, while the spec says it returns an atom."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"-spec f() -> atom().\nf() -> 1.\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that this will ",(0,r.jsx)(n.em,{children:"not"})," lead to a runtime error when running the Erlang program."]}),"\n",(0,r.jsx)(n.h2,{id:"bad_return_latent",children:"BAD_RETURN_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Bad Return Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#bad_return",children:"BAD_RETURN"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"biabduction_memory_leak",children:"BIABDUCTION_MEMORY_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"biabduction_retain_cycle",children:"BIABDUCTION_RETAIN_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#retain_cycle",children:"RETAIN_CYCLE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"block_parameter_not_null_checked",children:"BLOCK_PARAMETER_NOT_NULL_CHECKED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Block Parameter Not Null Checked" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-parameter-not-null-checked",children:"parameter-not-null-checked"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"})," first. If a ",(0,r.jsx)(n.code,{children:"nil"})," block is passed to\nthe method, then this will cause a crash. For example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nPossible solutions are adding a check for ",(0,r.jsx)(n.code,{children:"nil"}),", or making sure that the method\nis not ever called with ",(0,r.jsx)(n.code,{children:"nil"}),". When an argument will never be ",(0,r.jsx)(n.code,{children:"nil"}),", you can add\nthe annotation ",(0,r.jsx)(n.code,{children:"nonnull"})," to the argument's type, to tell Infer (and the type\nsystem), that the argument won't be ",(0,r.jsx)(n.code,{children:"nil"}),". This will silence the warning."]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L1" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.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,r.jsxs)(n.p,{children:["For example, ",(0,r.jsx)(n.code,{children:"int a[3]; a[5] = 42;"})," generates a ",(0,r.jsx)(n.code,{children:"BUFFER_OVERRUN_L1"})," on ",(0,r.jsx)(n.code,{children:"a[5] = 42;"}),"."]}),"\n",(0,r.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,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,r.jsx)(n.em,{children:"must"})," be unsafe. For example, array size: ",(0,r.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,r.jsx)(n.code,{children:"[5,5]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,r.jsx)(n.code,{children:"L1"}),", when it ",(0,r.jsx)(n.em,{children:"may"})," be unsafe. For example, array size:",(0,r.jsx)(n.code,{children:"[3,3]"}),",\noffset: ",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L5"}),": The least faithful report, when there is an interval top. For example, array size:\n",(0,r.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,r.jsx)(n.code,{children:"[-oo,+oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L4"}),": More faithful report than ",(0,r.jsx)(n.code,{children:"L5"}),", when there is an infinity value. For example, array size:\n",(0,r.jsx)(n.code,{children:"[3,3]"}),", offset: ",(0,r.jsx)(n.code,{children:"[0, +oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L3"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"S2"}),": An array access is unsafe by symbolic values. For example, array size: ",(0,r.jsx)(n.code,{children:"[n,n]"}),", offset\n",(0,r.jsx)(n.code,{children:"[n,+oo]"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"U5"}),": An array access is unsafe by unknown values, which are usually from unknown function\ncalls."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l2",children:"BUFFER_OVERRUN_L2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l3",children:"BUFFER_OVERRUN_L3"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L3" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l4",children:"BUFFER_OVERRUN_L4"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L4" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_l5",children:"BUFFER_OVERRUN_L5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun L5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_s2",children:"BUFFER_OVERRUN_S2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun S2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"buffer_overrun_u5",children:"BUFFER_OVERRUN_U5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Buffer Overrun U5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#buffer_overrun_l1",children:"BUFFER_OVERRUN_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"captured_strong_self",children:"CAPTURED_STRONG_SELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Captured strongSelf" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check is about when a strong pointer to ",(0,r.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,r.jsx)(n.p,{children:"This will happen in one of two cases generally:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["One uses ",(0,r.jsx)(n.code,{children:"weakSelf"})," but forgot to declare it weak first."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"})," Replace the first line with ",(0,r.jsx)(n.code,{children:"__weak __typeof(self) weakSelf = self;"}),"."]}),"\n",(0,r.jsxs)(n.ol,{start:"2",children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["One is using ",(0,r.jsx)(n.code,{children:"strongSelf"}),", declared in a block, in another inner block.\nThe retain cycle is avoided in the outer block because ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a\nlocal variable of the block. If ",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this example, ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a captured variable of the inner block, and this could cause retain cycles."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"})," Use a new pointer to self local to the inner block. In the example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Or, to improve readability, move the inner block logic into a separate method."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_allocates_memory",children:"CHECKERS_ALLOCATES_MEMORY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Allocates Memory" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@NoAllocation"})," transitively calls ",(0,r.jsx)(n.code,{children:"new"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"class C implements I {\n @NoAllocation\n void directlyAllocatingMethod() {\n new Object();\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"checkers_annotation_reachability_error",children:"CHECKERS_ANNOTATION_REACHABILITY_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Annotation Reachability Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with an annotation ",(0,r.jsx)(n.code,{children:"@A"})," transitively calls a method annotated ",(0,r.jsx)(n.code,{children:"@B"})," where the combination of annotations is forbidden (for example, ",(0,r.jsx)(n.code,{children:"@UiThread"})," calling ",(0,r.jsx)(n.code,{children:"@WorkerThread"}),")."]}),"\n",(0,r.jsx)(n.h2,{id:"checkers_calls_expensive_method",children:"CHECKERS_CALLS_EXPENSIVE_METHOD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Expensive Method Called" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@PerformanceCritical"})," transitively calls a method annotated ",(0,r.jsx)(n.code,{children:"@Expensive"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_expensive_overrides_unannotated",children:"CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Overrides Unannotated" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-annotation-reachability",children:"annotation-reachability"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method annotated with ",(0,r.jsx)(n.code,{children:"@Expensive"})," overrides an un-annotated method."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"checkers_fragment_retains_view",children:"CHECKERS_FRAGMENT_RETAINS_VIEW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Fragment Retains View" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-fragment-retains-view",children:"fragment-retains-view"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error type is Android-specific. It fires when a ",(0,r.jsx)(n.code,{children:"Fragment"})," type fails to\nnullify one or more of its declared ",(0,r.jsx)(n.code,{children:"View"})," fields in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),". In\nperformance-sensitive applications, a ",(0,r.jsx)(n.code,{children:"Fragment"})," should initialize all ",(0,r.jsx)(n.code,{children:"View"}),"'s\nin ",(0,r.jsx)(n.code,{children:"onCreateView"})," and nullify them in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),". If a ",(0,r.jsx)(n.code,{children:"Fragment"})," is placed\non the back stack and fails to nullify a ",(0,r.jsx)(n.code,{children:"View"})," in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),", it will\nretain a useless reference to that ",(0,r.jsx)(n.code,{children:"View"})," that will not be cleaned up until the\n",(0,r.jsx)(n.code,{children:"Fragment"})," is resumed or destroyed."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Nullify the ",(0,r.jsx)(n.code,{children:"View"})," in question in ",(0,r.jsx)(n.code,{children:"onDestroyView"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"compared_to_null_and_dereferenced",children:"COMPARED_TO_NULL_AND_DEREFERENCED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Compared To Null And Dereferenced" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A pointer that has both been compared to null, whcich suggests that it could be null, but has also been dereferenced without a null check."}),"\n",(0,r.jsx)(n.h2,{id:"config_impact",children:"CONFIG_IMPACT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Config Impact" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when an ",(0,r.jsx)(n.em,{children:"expensive"})," function is called without a ",(0,r.jsx)(n.em,{children:"config check"}),". The\n",(0,r.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,r.jsxs)(n.p,{children:["Similar to ",(0,r.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,r.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version1\nfoo();\nif (config_check){\n bar();\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"which is then modified to next"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version2\nfoo();\nif (config_check){\n bar();\n}\ngoo(); // added\n"})}),"\n",(0,r.jsxs)(n.p,{children:['the analysis would warn the developer that "',(0,r.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,r.jsx)(n.code,{children:"goo()"})," right after ",(0,r.jsx)(n.code,{children:"bar()"}),", then\nInfer wouldn't warn about it because it is already gated under the ",(0,r.jsx)(n.code,{children:"config_check"}),"."]}),"\n",(0,r.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,r.jsx)(n.code,{children:"version1"})," to ",(0,r.jsx)(n.code,{children:"version3"})," below by calling ",(0,r.jsx)(n.code,{children:"goo()"})," in ",(0,r.jsx)(n.code,{children:"foo()"}),","]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"// version3\nvoid foo(){\n // ....\n goo(); // added\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["then the analysis will report a ",(0,r.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue on the ungated call site of ",(0,r.jsx)(n.code,{children:"foo()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Currently, the analysis supports both Objective-C and Java but not C++."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"config_impact_strict",children:"CONFIG_IMPACT_STRICT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#ungated-code",children:"Ungated code"}),'. Reported as "Config Impact Strict" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-config-impact-analysis",children:"config-impact-analysis"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.jsxs)(n.a,{href:"#config_impact",children:[(0,r.jsx)(n.code,{children:"CONFIG_IMPACT"})," issue"]})," but the analysis reports ",(0,r.jsx)(n.strong,{children:"all"})," ungated\ncodes irrespective of whether they are expensive or not."]}),"\n",(0,r.jsx)(n.h2,{id:"config_usage",children:"CONFIG_USAGE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Config Usage" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when a ",(0,r.jsx)(n.em,{children:"config"})," value is used as branch condition in a function. The\n",(0,r.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,r.jsx)(n.p,{children:"For instance, if we have the following code"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'void foo() {\n if(config_check("my_new_feature")){ ... }\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:['then analysis would provide information that "the function ',(0,r.jsx)(n.code,{children:"foo"})," uses the config ",(0,r.jsx)(n.code,{children:"my_new_feature"}),' as\nbranch condition".']}),"\n",(0,r.jsx)(n.p,{children:"Note: This type of issue is only for providing semantic information, rather than warning or\nreporting actual problem."}),"\n",(0,r.jsx)(n.h2,{id:"constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Constant Address Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"#nullptr_dereference",children:(0,r.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," error type that is\nreported when the address is a constant other than zero."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, ",(0,r.jsx)(n.code,{children:"int *p = (int *) 123; *p = 42;"})," generates a ",(0,r.jsx)(n.code,{children:"CONSTANT_ADDRESS_DEREFERENCE"})," on ",(0,r.jsx)(n.code,{children:"*p = 42;"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["For more information see the ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:(0,r.jsx)(n.code,{children:"NULLPTR_DEREFERENCE"})})," issue type."]}),"\n",(0,r.jsx)(n.h2,{id:"constant_address_dereference_latent",children:"CONSTANT_ADDRESS_DEREFERENCE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Constant Address Dereference Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#constant_address_dereference",children:"CONSTANT_ADDRESS_DEREFERENCE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"cxx_ref_captured_in_block",children:"CXX_REF_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "C++ Reference Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.h2,{id:"cxx_string_captured_in_block",children:"CXX_STRING_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "C++ String Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,r.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" std::string fullName;\n const char* c = fullName.c_str();\n dispatch_async(dispatch_get_main_queue(), ^{\n const char* c1 = c;\n });\n"})}),"\n",(0,r.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,r.jsx)(n.h2,{id:"dangling_pointer_dereference",children:"DANGLING_POINTER_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Dangling Pointer Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.h2,{id:"data_flow_to_sink",children:"DATA_FLOW_TO_SINK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Data Flow to Sink" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A flow of data was detected to a sink."}),"\n",(0,r.jsx)(n.h2,{id:"deadlock",children:"DEADLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Deadlock" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsxs)(n.p,{children:["Old-style containers such as ",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Infer has support for detecting these deadlocks too."}),"\n",(0,r.jsxs)(n.p,{children:["To suppress reports of deadlocks in a method ",(0,r.jsx)(n.code,{children:"m()"})," use the\n",(0,r.jsx)(n.code,{children:'@SuppressLint("DEADLOCK")'})," annotation, as follows:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("DEADLOCK")\n public void m() {\n ...\n }\n'})}),"\n",(0,r.jsx)(n.h2,{id:"dead_store",children:"DEAD_STORE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Dead Store" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-liveness",children:"liveness"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"int i = 1; i = 2; return i;"}),")."]}),"\n",(0,r.jsx)(n.h2,{id:"divide_by_zero",children:"DIVIDE_BY_ZERO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Divide By Zero" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.h2,{id:"empty_vector_access",children:"EMPTY_VECTOR_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Empty Vector Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This error type is reported only in C++, in versions >= C++11."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"execution_time_complexity_increase",children:"EXECUTION_TIME_COMPLEXITY_INCREASE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-cost#examples-execution-cost",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"execution_time_complexity_increase_ui_thread",children:"EXECUTION_TIME_COMPLEXITY_INCREASE_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Complexity Increase Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Infer reports this issue when the execution time complexity of the procedure increases in degree ",(0,r.jsx)(n.strong,{children:"and"})," the procedure runs on the UI (main) thread."]}),"\n",(0,r.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,r.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,r.jsxs)(n.li,{children:["The method or its callees call a ",(0,r.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"execution_time_unreachable_at_exit",children:"EXECUTION_TIME_UNREACHABLE_AT_EXIT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Execution Time Unreachable At Exit" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Examples:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"expensive_execution_time",children:"EXPENSIVE_EXECUTION_TIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Execution Time" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"enabled=true"})," in ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/base/costKind.ml#L55",children:"costKind.ml"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"For instance, a simple example where we report this issue is a function with linear cost:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"expensive_loop_invariant_call",children:"EXPENSIVE_LOOP_INVARIANT_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Expensive Loop Invariant Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["We report this issue type when a function is ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"})," analysis)."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"guardedby_violation",children:"GUARDEDBY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "GuardedBy Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A field annotated with ",(0,r.jsx)(n.code,{children:"@GuardedBy"})," is being accessed by a call-chain that starts at a non-private method without synchronization."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Action: Protect the offending access by acquiring the lock indicated by the ",(0,r.jsx)(n.code,{children:"@GuardedBy(...)"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"impure_function",children:"IMPURE_FUNCTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Impure Function" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue type indicates impure functions. For instance, below functions would be marked as impure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"inefficient_keyset_iterator",children:"INEFFICIENT_KEYSET_ITERATOR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Inefficient Keyset Iterator" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-inefficient-keyset-iterator",children:"inefficient-keyset-iterator"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue is raised when"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["iterating over a HashMap with ",(0,r.jsx)(n.code,{children:"keySet()"})," iterator"]}),"\n",(0,r.jsx)(n.li,{children:"looking up the key each time"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Instead, it is more efficient to iterate over the loop with ",(0,r.jsx)(n.code,{children:"entrySet"})," which returns key-vaue pairs and gets rid of the hashMap lookup."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"inferbo_alloc_is_big",children:"INFERBO_ALLOC_IS_BIG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Big" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is passed a large constant value (>=10^6). For example, ",(0,r.jsx)(n.code,{children:"int n = 1000000; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_BIG"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument or make sure it is really needed."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_is_negative",children:"INFERBO_ALLOC_IS_NEGATIVE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Negative" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is called with a negative size. For example, ",(0,r.jsx)(n.code,{children:"int n = 3 - 5; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_NEGATIVE"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_is_zero",children:"INFERBO_ALLOC_IS_ZERO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc Is Zero" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," is called with a zero size. For example, ",(0,r.jsx)(n.code,{children:"int n = 3 - 3; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_IS_ZERO"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Action: Fix the size argument."}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_may_be_big",children:"INFERBO_ALLOC_MAY_BE_BIG"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc May Be Big" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," ",(0,r.jsx)(n.em,{children:"may"})," be called with a large value. For example, ",(0,r.jsx)(n.code,{children:"int n = b ? 3 : 1000000; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_BIG"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,r.jsx)(n.code,{children:"if (n < A_SMALL_NUMBER) { malloc(n); }"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"inferbo_alloc_may_be_negative",children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Alloc May Be Negative" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"malloc"})," ",(0,r.jsx)(n.em,{children:"may"})," be called with a negative value. For example, ",(0,r.jsx)(n.code,{children:"int n = b ? 3 : -5; malloc(n);"})," generates ",(0,r.jsx)(n.code,{children:"INFERBO_ALLOC_MAY_BE_NEGATIVE"})," on ",(0,r.jsx)(n.code,{children:"malloc(n)"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Action: Fix the size argument or add a bound checking, e.g. ",(0,r.jsx)(n.code,{children:"if (n > 0) { malloc(n); }"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"infinite_execution_time",children:"INFINITE_EXECUTION_TIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Infinite Execution Time" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-cost",children:"cost"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"example-1-t-due-to-expressivity",children:"Example 1: T due to expressivity"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"example-2-t-due-to-unmodeled-calls",children:"Example 2: T due to unmodeled calls"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Here, Infer does not have any InferBo models for the range of values returned by ",(0,r.jsx)(n.code,{children:"String.toCharArray"}),", hence it cannot determine that we will be iterating over a char array in the size of ",(0,r.jsx)(n.code,{children:"input"})," string."]}),"\n",(0,r.jsxs)(n.p,{children:["To teach InferBo about such library calls, they should be semantically modeled in ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/infer/blob/main/infer/src/bufferoverrun/bufferOverrunModels.ml",children:"InferBo"}),"."]}),"\n",(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"infinite_recursion",children:"INFINITE_RECURSION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Infinite Recursion" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A special case of ",(0,r.jsx)(n.a,{href:"#mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"})," where we detected that the recursive call is made with the exact same values, which guarantees an infinite recursion."]}),"\n",(0,r.jsx)(n.h2,{id:"integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L1" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is reported when integer overflow occurred by integer operations such as addition, subtraction,\nand multiplication. For example, ",(0,r.jsx)(n.code,{children:"int n = INT_MAX; int m = n + 3;"})," generates a INTEGER_OVERFLOW_L1\non ",(0,r.jsx)(n.code,{children:"n + 3"}),"."]}),"\n",(0,r.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,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L1"}),": The most faithful report, when it ",(0,r.jsx)(n.em,{children:"must"})," be unsafe. For example,\n",(0,r.jsx)(n.code,{children:"[2147483647,2147483647] + [1,1]"})," in 32-bit signed integer type."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L2"}),": Less faithful report than ",(0,r.jsx)(n.code,{children:"L1"}),", when it ",(0,r.jsx)(n.em,{children:"may"})," be unsafe. For example,\n",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"L5"}),": The reports that are not included in the above cases."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.jsx)(n.h2,{id:"integer_overflow_l2",children:"INTEGER_OVERFLOW_L2"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L2" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"integer_overflow_l5",children:"INTEGER_OVERFLOW_L5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow L5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"integer_overflow_u5",children:"INTEGER_OVERFLOW_U5"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Integer Overflow U5" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-bufferoverrun",children:"bufferoverrun"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#integer_overflow_l1",children:"INTEGER_OVERFLOW_L1"})]}),"\n",(0,r.jsx)(n.h2,{id:"interface_not_thread_safe",children:"INTERFACE_NOT_THREAD_SAFE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Interface Not Thread Safe" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error indicates that you have invoked an interface method not annotated\nwith ",(0,r.jsx)(n.code,{children:"@ThreadSafe"})," from a thread-safe context (e.g., code that uses locks or is\nmarked ",(0,r.jsx)(n.code,{children:"@ThreadSafe"}),"). The fix is to add the ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-racerd#interface-not-thread-safe",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"invalid_sil",children:"INVALID_SIL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Invalid Sil" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-sil-validation",children:"sil-validation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"invariant_call",children:"INVARIANT_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Invariant Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-loop-hoisting",children:"loop-hoisting"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"We report this issue type when a function call is loop-invariant and hoistable, i.e."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"the function has no side side effects (pure)"}),"\n",(0,r.jsx)(n.li,{children:"has invariant arguments and result (i.e. have the same value in all loop iterations)"}),"\n",(0,r.jsx)(n.li,{children:"it is guaranteed to execute, i.e. it dominates all loop sources"}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"ipc_on_ui_thread",children:"IPC_ON_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Ipc On Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A blocking ",(0,r.jsx)(n.code,{children:"Binder"})," IPC call occurs on the UI thread."]}),"\n",(0,r.jsx)(n.h2,{id:"lab_resource_leak",children:"LAB_RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Lab Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-resource-leak-lab",children:"resource-leak-lab"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Toy issue."}),"\n",(0,r.jsx)(n.h2,{id:"lineage_flow",children:"LINEAGE_FLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Lineage Flow" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-lineage",children:"lineage"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A Lineage taint flow has been detected from a source to a sink."}),"\n",(0,r.jsx)(n.h2,{id:"lockless_violation",children:"LOCKLESS_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Lockless Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A method implements an interface signature annotated with ",(0,r.jsx)(n.code,{children:"@Lockless"})," but which transitively acquires a lock."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"lock_consistency_violation",children:"LOCK_CONSISTENCY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Lock Consistency Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This is an error reported on C++ and Objective C classes whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Some class method directly uses locking primitives (not transitively)."}),"\n",(0,r.jsxs)(n.li,{children:["It has a public method which writes to some member ",(0,r.jsx)(n.code,{children:"x"})," while holding a lock."]}),"\n",(0,r.jsxs)(n.li,{children:["It has a public method which reads ",(0,r.jsx)(n.code,{children:"x"})," without holding a lock."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The above may happen through a chain of calls. Above, ",(0,r.jsx)(n.code,{children:"x"})," may also be a\ncontainer (an array, a vector, etc)."]}),"\n",(0,r.jsx)(n.h3,{id:"fixing-lock-consistency-violation-reports",children:"Fixing Lock Consistency Violation reports"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Avoid the offending access (most often the read). Of course, this may not be\npossible."}),"\n",(0,r.jsx)(n.li,{children:"Use synchronization to protect the read, by using the same lock protecting the\ncorresponding write."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"lock_on_ui_thread",children:"LOCK_ON_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Lock on UI Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A method annoted as being on UIThread acquires a lock. This could be a potential performance issue"}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"class Example {\n @UiThread\n void foo() {\n synchronized(this) {\n }\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"memory_leak_c",children:"MEMORY_LEAK_C"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.h3,{id:"memory-leak-in-c",children:"Memory leak in C"}),"\n",(0,r.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,r.jsxs)(n.p,{children:["In C, Infer reports memory leaks when objects are created with ",(0,r.jsx)(n.code,{children:"malloc"})," and not\nfreed. For example:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-c",children:"-(void) memory_leak_bug {\n struct Person *p = malloc(sizeof(struct Person));\n}\n"})}),"\n",(0,r.jsx)(n.h3,{id:"memory-leak-in-objective-c",children:"Memory leak in Objective-C"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"memory_leak_cpp",children:"MEMORY_LEAK_CPP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Memory Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#memory_leak_c",children:"MEMORY_LEAK_C"})]}),"\n",(0,r.jsx)(n.h2,{id:"missing_required_prop",children:"MISSING_REQUIRED_PROP"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Missing Required Prop" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-litho-required-props",children:"litho-required-props"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issues is reported when a required ",(0,r.jsx)(n.code,{children:"@Prop"})," is missing."]}),"\n",(0,r.jsx)(n.h2,{id:"examples",children:"Examples"}),"\n",(0,r.jsxs)(n.p,{children:["Assume that the following Litho Component specification is defined as follows where ",(0,r.jsx)(n.code,{children:"prop1"})," is optional and ",(0,r.jsx)(n.code,{children:"prop2"})," is required."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.code,{children:"prop1"})," below), it is ok."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:"MyComponent.create(c)\n .prop2(8)\n .build();\n"})}),"\n",(0,r.jsxs)(n.p,{children:["However, if we are missing a required prop, Infer gives an error below for the missing ",(0,r.jsx)(n.code,{children:"prop2"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:'MyComponent.create(c)\n .prop1("My prop 1")\n .build();\n'})}),"\n",(0,r.jsx)(n.p,{children:"** Action **"}),"\n",(0,r.jsx)(n.p,{children:"There are two ways to fix this issue."}),"\n",(0,r.jsxs)(n.p,{children:["First, we could add the missing ",(0,r.jsx)(n.code,{children:"prop2"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["or alternatively, if the ",(0,r.jsx)(n.code,{children:"prop2"})," is not really required, we could change the component spec to reflect that:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"mixed_self_weakself",children:"MIXED_SELF_WEAKSELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Mixed Self WeakSelf" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports an issue when an Objective-C block captures both ",(0,r.jsx)(n.code,{children:"self"})," and ",(0,r.jsx)(n.code,{children:"weakSelf"}),", a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),".\nPossibly the developer meant to capture only ",(0,r.jsx)(n.code,{children:"weakSelf"})," to avoid a retain cycle, but made a typo and used ",(0,r.jsx)(n.code,{children:"self"}),"\ninstead of ",(0,r.jsx)(n.code,{children:"strongSelf"}),". In this case, this could cause a retain cycle."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),": Fixing the typo is generally the right course of action."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"modifies_immutable",children:"MODIFIES_IMMUTABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Modifies Immutable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-impurity",children:"impurity"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue type indicates modifications to fields marked as @Immutable. For instance, below function ",(0,r.jsx)(n.code,{children:"mutateArray"})," would be marked as modifying immutable field ",(0,r.jsx)(n.code,{children:"testArray"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"multiple_weakself",children:"MULTIPLE_WEAKSELF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Multiple WeakSelf Use" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when an Objective-C block uses ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),") more than once.\nThis could lead to unexpected behaviour. Even if ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"})," points to could be freed anytime."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"}),"\nOne should assign ",(0,r.jsx)(n.code,{children:"weakSelf"})," to a strong pointer first, and then\nuse it in the block."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"mutual_recursion_cycle",children:"MUTUAL_RECURSION_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Mutual Recursion Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A recursive call or mutually recursive call has been detected. This does ",(0,r.jsx)(n.em,{children:"not"})," mean that the program won't terminate, just that the code is recursive. You should double-check if the recursion is intended and if it can lead to non-termination or a stack overflow."]}),"\n",(0,r.jsx)(n.p,{children:"Example of recursive function:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-C",children:"int factorial(int x) {\n if (x > 0) {\n return x * factorial(x-1);\n } else {\n return 1;\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"nil_block_call",children:"NIL_BLOCK_CALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when one tries to call an Objective-C block that is ",(0,r.jsx)(n.code,{children:"nil"}),".\nThis causes a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Adding a check for ",(0,r.jsx)(n.code,{children:"nil"})," before calling the block, or making sure never to call the method ",(0,r.jsx)(n.code,{children:"foo:"})," with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_block_call_latent",children:"NIL_BLOCK_CALL_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Nil Block Call Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_block_call",children:"NIL_BLOCK_CALL"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This checks reports when ",(0,r.jsx)(n.code,{children:"nil"})," is passed to collections in Objective-C such as arrays and dictionaries. This causes a crash."]}),"\n",(0,r.jsx)(n.h3,{id:"arrays",children:"Arrays"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"dictionaries",children:"Dictionaries"}),"\n",(0,r.jsxs)(n.p,{children:["Adding a ",(0,r.jsx)(n.code,{children:"nil"})," value in a dictionary causes a crash. If the concept of ",(0,r.jsx)(n.code,{children:"nil"})," is required, one can add\n",(0,r.jsx)(n.code,{children:"[NSNull null]"})," instead."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Retrieving or removing an object from a dictionary with a ",(0,r.jsx)(n.code,{children:"nil"})," key also causes a crash:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:' id key = nil;\n mDict[key] = @"somestring"; //crash\n\n [mDict removeObjectForKey:nil]; //crash\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["In all the cases above, when passing ",(0,r.jsx)(n.code,{children:"nil"})," causes a crash, the solutions are either making sure\nthat the object passed will never be ",(0,r.jsx)(n.code,{children:"nil"}),", or adding a check for ",(0,r.jsx)(n.code,{children:"nil"})," before calling those methods."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_insertion_into_collection_latent",children:"NIL_INSERTION_INTO_COLLECTION_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Nil Insertion Into Collection" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_insertion_into_collection",children:"NIL_INSERTION_INTO_COLLECTION"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["In Objective-C, calling a method on ",(0,r.jsx)(n.code,{children:"nil"})," (or in Objective-C terms, sending a message to ",(0,r.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,r.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,r.jsx)(n.code,{children:"nil"})," causes undefined behaviour."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["To fix the above issue, we need to check if ",(0,r.jsx)(n.code,{children:"obj"})," is\nnot ",(0,r.jsx)(n.code,{children:"nil"})," before calling the ",(0,r.jsx)(n.code,{children:"returnsnonPOD"})," method:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"nil_messaging_to_non_pod_latent",children:"NIL_MESSAGING_TO_NON_POD_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Nil Messaging To Non Pod Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nil_messaging_to_non_pod",children:"NIL_MESSAGING_TO_NON_POD"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching branch is found when evaluating the ",(0,r.jsx)(n.code,{children:"of"})," section of a ",(0,r.jsx)(n.code,{children:"try"})," expression. Corresponds to the ",(0,r.jsx)(n.code,{children:"{try_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"no_matching_branch_in_try_latent",children:"NO_MATCHING_BRANCH_IN_TRY_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Branch In Try Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_branch_in_try",children:"NO_MATCHING_BRANCH_IN_TRY"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching case clause in Erlang: Reports an error when none of the clauses of a ",(0,r.jsx)(n.code,{children:"case"})," match the expression. Corresponds to the ",(0,r.jsx)(n.code,{children:"{case_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"tail(X) ->\n case X of\n [_|T] -> T\n end.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_case_clause_latent",children:"NO_MATCHING_CASE_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Case Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_case_clause",children:"NO_MATCHING_CASE_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["No matching else clause in Erlang: Reports an error when none of the clauses of an ",(0,r.jsx)(n.code,{children:"else"})," match the short-circuit result from ",(0,r.jsx)(n.code,{children:"maybe"})," body. Corresponds to the ",(0,r.jsx)(n.code,{children:"{else_clause,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, here the ",(0,r.jsx)(n.code,{children:"1 ?= 2"})," expression does not match and short-circuits to ",(0,r.jsx)(n.code,{children:"2"}),", which does not match the single clause under ",(0,r.jsx)(n.code,{children:"else"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"else_clause_error() ->\n maybe\n 1 ?= 2\n else\n 1 -> ok\n end.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_else_clause_latent",children:"NO_MATCHING_ELSE_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Else Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_else_clause",children:"NO_MATCHING_ELSE_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"function_clause"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"tail([])"})," and the full definition of ",(0,r.jsx)(n.code,{children:"tail"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"tail([_|Xs]) -> Xs.\n"})}),"\n",(0,r.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,r.jsx)(n.h2,{id:"no_matching_function_clause_latent",children:"NO_MATCHING_FUNCTION_CLAUSE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Matching Function Clause Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_matching_function_clause",children:"NO_MATCHING_FUNCTION_CLAUSE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"match"})," expression does not match the pattern on the left hand side. Corresponds to the ",(0,r.jsx)(n.code,{children:"{badmatch,V}"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, ",(0,r.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,r.jsx)(n.h2,{id:"no_match_of_rhs_latent",children:"NO_MATCH_OF_RHS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No Match Of Rhs Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_match_of_rhs",children:"NO_MATCH_OF_RHS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"if"})," expression evaluate to true. Corresponds to the ",(0,r.jsx)(n.code,{children:"if_clause"})," error in the Erlang runtime."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, if we call ",(0,r.jsx)(n.code,{children:"sign(0)"})," and the full definition of ",(0,r.jsx)(n.code,{children:"sign"})," is"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-erlang",children:"sign(X) ->\n if\n X > 0 -> positive;\n X < 0 -> negative\n end.\n"})}),"\n",(0,r.jsx)(n.h2,{id:"no_true_branch_in_if_latent",children:"NO_TRUE_BRANCH_IN_IF_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "No True Branch In If Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#no_true_branch_in_if",children:"NO_TRUE_BRANCH_IN_IF"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nsstring_internal_ptr_captured_in_block",children:"NSSTRING_INTERNAL_PTR_CAPTURED_IN_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "NSString Captured in Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when an internal pointer of a local variable of type ",(0,r.jsx)(n.code,{children:"std::string"})," is captured in an escaping block.\nThis means that the block will be leaving the current scope, i.e. it is\nnot annotated with ",(0,r.jsx)(n.code,{children:"__attribute__((noescape))"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:" std::string fullName;\n const char* c = fullName.c_str();\n dispatch_async(dispatch_get_main_queue(), ^{\n const char* c1 = c;\n });\n"})}),"\n",(0,r.jsx)(n.p,{children:"This could cause crashes because the variable is likely to be freed when the code is executed, leaving the pointer dangling."}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-java",children:"Null dereference in Java"}),"\n",(0,r.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,r.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Change the code to ensure that ",(0,r.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Add a check that ",(0,r.jsx)(n.code,{children:"p"})," is not ",(0,r.jsx)(n.code,{children:"null"})," before dereferencing ",(0,r.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,r.jsx)(n.code,{children:"p"}),"\nis ",(0,r.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,r.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["The call ",(0,r.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,r.jsx)(n.code,{children:"null"}),": if ",(0,r.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,r.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,r.jsxs)(n.p,{children:["Facebook NOTE: ",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-c",children:"Null dereference in C"}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-objective-c",children:"Null dereference in Objective-C"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,r.jsx)(n.code,{children:"nil"})," check either for ",(0,r.jsx)(n.code,{children:"param"})," above or for ",(0,r.jsx)(n.code,{children:"d"}),", or making sure that ",(0,r.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Calling a ",(0,r.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Moreover, inserting ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-java-1",children:"Null dereference in Java"}),"\n",(0,r.jsx)(n.p,{children:"Many of Infer's reports of potential Null Pointer Exceptions (NPE) come from code of the form"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"If you see code of this form, then you have several options."}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsxs)(n.strong,{children:["If you are unsure whether or not ",(0,r.jsx)(n.code,{children:"foo()"})," will return null"]}),", you should\nideally either"]}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Change the code to ensure that ",(0,r.jsx)(n.code,{children:"foo()"})," can not return null, or"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["Add a check that ",(0,r.jsx)(n.code,{children:"p"})," is not ",(0,r.jsx)(n.code,{children:"null"})," before dereferencing ",(0,r.jsx)(n.code,{children:"p"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Sometimes, in case (2) it is not obvious what you should do when ",(0,r.jsx)(n.code,{children:"p"}),"\nis ",(0,r.jsx)(n.code,{children:"null"}),". One possibility is to throw an exception, failing early but\nexplicitly. This can be done using ",(0,r.jsx)(n.code,{children:"checkNotNull"})," as in the following\ncode:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["The call ",(0,r.jsx)(n.code,{children:"checkNotNull(foo())"})," will never return ",(0,r.jsx)(n.code,{children:"null"}),": if ",(0,r.jsx)(n.code,{children:"foo()"}),"\nreturns ",(0,r.jsx)(n.code,{children:"null"})," then it fails early by throwing a Null Pointer\nException."]}),"\n",(0,r.jsxs)(n.p,{children:["Facebook NOTE: ",(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-c-1",children:"Null dereference in C"}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of an inter-procedural null dereference bug in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"null-dereference-in-objective-c-1",children:"Null dereference in Objective-C"}),"\n",(0,r.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,r.jsx)(n.code,{children:"nil"}),", but dereferencing a pointer directly does\ncause a crash."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":\nAdding a ",(0,r.jsx)(n.code,{children:"nil"})," check either for ",(0,r.jsx)(n.code,{children:"param"})," above or for ",(0,r.jsx)(n.code,{children:"d"}),", or making sure that ",(0,r.jsx)(n.code,{children:"foo:"})," will never\nbe called with ",(0,r.jsx)(n.code,{children:"nil"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Calling a ",(0,r.jsx)(n.code,{children:"nil"})," block will also cause a crash.\nWe have a dedicated issue type for this case: ",(0,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_block_call",children:"Nil Block Call"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["Moreover, inserting ",(0,r.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,r.jsx)(n.a,{href:"/docs/next/all-issue-types#nil_insertion_into_collection",children:"Nil Insertion Into Collection"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_in_nullsafe_class_latent",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nullptr_dereference_in_nullsafe_class",children:"NULLPTR_DEREFERENCE_IN_NULLSAFE_CLASS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"nullptr_dereference_latent",children:"NULLPTR_DEREFERENCE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"null_argument",children:"NULL_ARGUMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"null_argument_latent",children:"NULL_ARGUMENT_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Null Argument Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#null_argument",children:"NULL_ARGUMENT"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"null_dereference",children:"NULL_DEREFERENCE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#null-pointer-dereference",children:"Null pointer dereference"}),'. Reported as "Null Dereference" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#nullptr_dereference",children:"NULLPTR_DEREFERENCE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Optional Empty Access warnings are reported when we try to retrieve the value of a ",(0,r.jsx)(n.a,{href:"https://github.com/facebook/folly/blob/master/folly/Optional.h",children:(0,r.jsx)(n.code,{children:"folly::Optional"})})," when it is empty (i.e. ",(0,r.jsx)(n.code,{children:"folly::none"}),")."]}),"\n",(0,r.jsxs)(n.p,{children:["In the following example we get a warning as ",(0,r.jsx)(n.code,{children:"int_opt"})," might be ",(0,r.jsx)(n.code,{children:"folly::none"})," and its value is being accessed:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["We do not get the warning anymore if we add a check whether ",(0,r.jsx)(n.code,{children:"int_opt"})," is not empty:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"optional_empty_access_latent",children:"OPTIONAL_EMPTY_ACCESS_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Optional Empty Access Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#optional_empty_access",children:"OPTIONAL_EMPTY_ACCESS"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"premature_nil_termination_argument",children:"PREMATURE_NIL_TERMINATION_ARGUMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Premature Nil Termination Argument" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error type is reported in C and Objective-C. In many variadic methods,\n",(0,r.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,r.jsx)(n.code,{children:"nil"})," as well, Infer reports an error because that may\nlead to unexpected behavior."]}),"\n",(0,r.jsxs)(n.p,{children:["An example of such variadic methods is\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:' NSArray *foo = [NSArray arrayWithObjects: @"aaa", str, @"bbb", nil];\n'})}),"\n",(0,r.jsxs)(n.p,{children:["In this example, if ",(0,r.jsx)(n.code,{children:"str"})," is ",(0,r.jsx)(n.code,{children:"nil"})," then an array ",(0,r.jsx)(n.code,{children:'@[@"aaa"]'})," of size 1 will be\ncreated, and not an array ",(0,r.jsx)(n.code,{children:'@[@"aaa", str, @"bbb"]'})," of size 3 as expected."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_cannot_instantiate_abstract_class",children:"PULSE_CANNOT_INSTANTIATE_ABSTRACT_CLASS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Cannot Instantiate Abstract Class" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Instantiating an abstract class will lead to ",(0,r.jsx)(n.code,{children:"Cannot instantiate abstract class"})," error."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"abstract class AbstractClass1 {}\n\nclass ConcreteClass1 extends AbstractClass1 {}\n\npublic static function makeGeneric(classname $cls): void {\n new $cls();\n}\n\n<<__ConsistentConstruct>>\nabstract class AbstractClass2 {\n\n public static function makeStatic(): void {\n new static();\n }\n}\n\nclass ConcreteClass2 extends AbstractClass2 {}\n\npublic function badViaGeneric(): void {\n Main::makeGeneric(AbstractClass1::class); // ERROR!\n}\n\npublic function goodViaGeneric(): void {\n Main::makeGeneric(ConcreteClass1::class);\n}\n\npublic function badViaStatic(): void {\n AbstractClass2::makeStatic(); // ERROR!\n}\n\npublic function goodViaStatic(): void {\n ConcreteClass2::makeStatic();\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_const_refable",children:"PULSE_CONST_REFABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Const Refable Parameter" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"const&"})," so that no unnecessary copy is created at the callsite of the function."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_dict_missing_key",children:"PULSE_DICT_MISSING_KEY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dict Missing Key" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to warn\nreading a missing key of dictionary in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the dictionary ",(0,r.jsx)(n.code,{children:"$d"})," has no entry for ",(0,r.jsx)(n.code,{children:"bye"}),", so reading\n",(0,r.jsx)(n.code,{children:"$d['bye']"})," will throw the ",(0,r.jsx)(n.code,{children:"OutOfBoundsException"})," exception, which is usually unexpected from\ndevelopers. We can use a safer function ",(0,r.jsx)(n.code,{children:"idx"})," instead when keys of a dictionary is unclear."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_dynamic_type_mismatch",children:"PULSE_DYNAMIC_TYPE_MISMATCH"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Dynamic Type Mismatch" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This error is reported in Hack. It fires when we detect an operation that is incompatible\nwith the dynamic type of its arguments."}),"\n",(0,r.jsxs)(n.p,{children:["For example, reading ",(0,r.jsx)(n.code,{children:"$x['key']"})," when ",(0,r.jsx)(n.code,{children:"$x"})," is a vector."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_readonly_shared_ptr_param",children:"PULSE_READONLY_SHARED_PTR_PARAM"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Read-only Shared Parameter" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"std::shared_ptr::get"})," at callsites."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"can be changed to"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_reference_stability",children:"PULSE_REFERENCE_STABILITY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Reference Stability" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["The family of maps ",(0,r.jsx)(n.code,{children:"folly::F14ValueMap"}),", ",(0,r.jsx)(n.code,{children:"folly::F14VectorMap"}),", and by extension\n",(0,r.jsx)(n.code,{children:"folly::F14FastMap"})," differs slightly from ",(0,r.jsx)(n.code,{children:"std::unordered_map"})," as it does not\nprovide reference stability. When the map resizes such as when ",(0,r.jsx)(n.code,{children:"reserve"})," is\ncalled or new elements are added, all existing references become invalid and\nshould not be used."]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.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,r.jsx)(n.code,{children:"at"}),", ",(0,r.jsx)(n.code,{children:"find"}),", ",(0,r.jsx)(n.code,{children:"emplace"}),", or ",(0,r.jsx)(n.code,{children:"insert_or_assign"})," to increase code quality and\nsafety."]}),"\n",(0,r.jsx)(n.p,{children:"Examples:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_resource_leak",children:"PULSE_RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#resource_leak",children:"RESOURCE_LEAK"})]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_transitive_access",children:"PULSE_TRANSITIVE_ACCESS"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#logic-error",children:"Logic error"}),'. Reported as "Transitive Access" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue tracks spurious accesses that are reachable from specific entry functions."}),"\n",(0,r.jsx)(n.p,{children:"Spurious accesses are specified as specific load/calls."}),"\n",(0,r.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,r.jsx)(n.h2,{id:"pulse_unawaited_awaitable",children:"PULSE_UNAWAITED_AWAITABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unawaited Awaitable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"Awaitable"})," values created by calls to asynchronous methods should eventually be ",(0,r.jsx)(n.code,{children:"await"}),"ed along all codepaths (even if their value is unused). Hence the following is ",(0,r.jsx)(n.em,{children:"not"})," OK"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["Failure to ",(0,r.jsx)(n.code,{children:"await"})," an ",(0,r.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,r.jsx)(n.code,{children:"T"})," and ",(0,r.jsx)(n.code,{children:"Awaitable"})," that may not be caught by the type-checker."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unfinished_builder",children:"PULSE_UNFINISHED_BUILDER"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Unfinished Builder" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Classes adhering to builder pattern are usually expected to call a finalizer function at some point to produce final result based on values that were passed to a builder itself. If finalizer function hasn't been called then builder's data won't be consumed in any meaningful way and will just be discarded."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"class MyBuilder {\n private int $a = 0;\n private int $b = 0;\n\n public function setA(int $a): MyBuilder {\n $this->a = $a;\n return $this;\n }\n\n public function setB(int $b): MyBuilder {\n $this->b = $b;\n return $this;\n }\n\n public function saveX(): Awaitable {\n // typically do something involving IO\n }\n}\n\nclass BuilderTester {\n public static function builderUserOK(): void {\n $b = new MyBuilder(0);\n $b->setA(42)->setB(97)->saveX();\n }\n\n public static function builderUserBad(): void {\n $b = new MyBuilder(0);\n $b->setA(42)->setB(97); // ERROR: saveX hasn't been called so the builder's data is discarded\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_uninitialized_const",children:"PULSE_UNINITIALIZED_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_value",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_VALUE"})}),", but it is to detect the uninitialized abstract const value in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the ",(0,r.jsx)(n.code,{children:"FIELD"})," can be read by the static method ",(0,r.jsx)(n.code,{children:"get_field"}),"."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["It is problematic invoking ",(0,r.jsx)(n.code,{children:"static::FIELD"}),", since it may be resolved to a ",(0,r.jsx)(n.code,{children:"A::FIELD"})," access, if called from ",(0,r.jsx)(n.code,{children:"A::get_field()"}),". Because ",(0,r.jsx)(n.code,{children:"FIELD"})," is abstract in ",(0,r.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,r.jsxs)(n.li,{children:["In the ",(0,r.jsx)(n.code,{children:"B"})," class, ",(0,r.jsx)(n.code,{children:"FIELD"})," is initialized, thus invoking ",(0,r.jsx)(n.code,{children:"B::get_field"})," is safe."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_uninitialized_method",children:"PULSE_UNINITIALIZED_METHOD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#runtime-exception",children:"Runtime exception"}),'. Reported as "Uninitialized Method" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This issue is similar to ",(0,r.jsx)(n.a,{href:"#pulse_uninitialized_const",children:(0,r.jsx)(n.code,{children:"PULSE_UNINITIALIZED_CONST"})}),", but it is to detect the uninitialized method call in Hack."]}),"\n",(0,r.jsxs)(n.p,{children:["For example, in the following code, the static method ",(0,r.jsx)(n.code,{children:"foo"})," is declared only in the interface and the abstract class. Thus, calling the static method can introduce an unexpected exception or a fatal error, while the type checker does miss the issue."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-hack",children:"interface MyInterface {\n public static function foo(): string;\n}\n\nabstract class MyAbstractClass {\n public abstract static function foo(): string;\n}\n\nfunction interface_method_static_method_bad(): string {\n // Uncaught exception 'TypehintViolationException'\n $c = MyInterface::class;\n return $c::foo();\n}\n\nfunction abstract_class_static_method_bad(): string {\n // Fatal error: Cannot call abstract method\n $c = MyAbstractClass::class;\n return $c::foo();\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"pulse_uninitialized_value",children:"PULSE_UNINITIALIZED_VALUE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Uninitialized Value" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"The code uses a variable that has not been initialized, leading to unpredictable or unintended results."}),"\n",(0,r.jsx)(n.p,{children:"Using uninitialized values can lead to undefined behaviors possibly resulting in crashes, security failures and invalid results."}),"\n",(0,r.jsx)(n.p,{children:"This can easily be fixed by assigning all variables to an initial value when declaring them."}),"\n",(0,r.jsx)(n.p,{children:"This, for example, in C:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_const",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_assignment_movable",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT_MOVABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment Movable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.code,{children:"const &"}),"."]}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this case, when we call ",(0,r.jsx)(n.code,{children:"callee"}),", under the hood, a copy of the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is created to be passed to the function call. However, the copy might be unnecessary if"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"callee"})," doesn\u2019t modify its parameter \u2192 then we can change its type to ",(0,r.jsx)(n.code,{children:"const ExpensiveObject&"}),", getting rid of the copy at caller"]}),"\n",(0,r.jsxs)(n.li,{children:["even if ",(0,r.jsx)(n.code,{children:"callee"})," might modify the object, if the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is never used later on, we can get rid of the copy by moving it instead: ",(0,r.jsx)(n.code,{children:"callee(std::move(myExpensiveObj))"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The analysis is careful about suggesting moves blindly though: if the argument ",(0,r.jsx)(n.code,{children:"myExpensiveObj"})," is of type ",(0,r.jsx)(n.code,{children:"const & ExpensiveObject"})," then we also recommend that for move to work, const-reference needs to be removed."]}),"\n",(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_intermediate_const",children:"PULSE_UNNECESSARY_COPY_INTERMEDIATE_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Intermediate from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy",children:"PULSE_UNNECESSARY_COPY"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_movable",children:"PULSE_UNNECESSARY_COPY_MOVABLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Movable" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This is reported when Infer detects an unnecessary copy into a field where"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"the source is an rvalue-reference"}),"\n",(0,r.jsx)(n.li,{children:"the source is not modified before it goes out of scope or is destroyed."}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Note that the copy can be modified since it has the ownership of the object."}),"\n",(0,r.jsx)(n.p,{children:"Fix: Rather than the copying into the field, the source should be moved into it."}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is reported when Infer detects an unnecessary copy of an object via ",(0,r.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,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_optional_const",children:"PULSE_UNNECESSARY_COPY_OPTIONAL_CONST"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy to Optional from Const" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_optional",children:"PULSE_UNNECESSARY_COPY_OPTIONAL"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_return",children:"PULSE_UNNECESSARY_COPY_RETURN"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Return" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.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,r.jsx)(n.code,{children:"std::move"})," to avoid the copy."]}),"\n",(0,r.jsx)(n.p,{children:"For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"pulse_unnecessary_copy_thrift_assignment",children:"PULSE_UNNECESSARY_COPY_THRIFT_ASSIGNMENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Unnecessary Copy Assignment into Thrift" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This is similar to ",(0,r.jsx)(n.a,{href:"#pulse_unnecessary_copy_assignment",children:"PULSE_UNNECESSARY_COPY_ASSIGNMENT"}),", but is\nreported when copied into thrift fields."]}),"\n",(0,r.jsx)(n.h2,{id:"pure_function",children:"PURE_FUNCTION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Pure Function" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-purity",children:"purity"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"This issue type indicates pure functions. For instance, below functions would be marked as pure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"However, the following ones would not be pure:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"regex_op_on_ui_thread",children:"REGEX_OP_ON_UI_THREAD"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Regex Op On Ui Thread" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A potentially costly operation on a regular expression occurs on the UI thread."}),"\n",(0,r.jsx)(n.h2,{id:"resource_leak",children:"RESOURCE_LEAK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Resource Leak" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-biabduction",children:"biabduction"}),"."]})}),"\n",(0,r.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,r.jsx)(n.h3,{id:"resource-leak-in-c",children:"Resource leak in C"}),"\n",(0,r.jsx)(n.p,{children:"This is an example of a resource leak in C code:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h3,{id:"resource-leak-in-java",children:"Resource leak in Java"}),"\n",(0,r.jsx)(n.p,{children:"For the remaining of this section, we will consider examples of resource leaks\nin Java code."}),"\n",(0,r.jsxs)(n.p,{children:["TIP: A common source of bugs is ",(0,r.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,r.jsx)(n.h3,{id:"basics-and-standard-idiom",children:"Basics and Standard Idiom"}),"\n",(0,r.jsxs)(n.p,{children:["Some objects in Java, the ",(0,r.jsx)("i",{children:"resources"}),", are supposed to be closed when you\nstop using them, and failure to close is a ",(0,r.jsx)("i",{children:"resource leak"}),". Resources\ninclude input streams, output streams, readers, writers, sockets, http\nconnections, cursors, and json parsers."]}),"\n",(0,r.jsx)(n.p,{children:"The standard idiom is"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"or more for example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"where an exception in fos.write will cause execution to skip past the close()\nstatement."}),"\n",(0,r.jsx)(n.h4,{id:"multiple-resources-bugs",children:"Multiple Resources Bugs"}),"\n",(0,r.jsx)(n.p,{children:"We can deal with multiple resources correctly and simply just by nesting the\nstandard idiom."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Bugs often occur when using multiple resources in other ways because of\nexceptions in close() methods. For example,"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.p,{children:"Another way, besides the standard idiom, to deal with this problem is to swallow\nexceptions."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.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,r.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,r.jsx)(n.h3,{id:"nested_allocations",children:"Nested_Allocations"}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.p,{children:"Here are resources that can throw exceptions i their constructor(s)."}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"ObjectInputStream , ObjectOutputStream, PipedInputStream, PipedOutputStream,\nPipedReader, PipedWriter, JarInputStream, JarOutputStream, GZIPInputStream,\nGZIPOutputStream , ZipFile all throw IOException"}),"\n",(0,r.jsx)(n.li,{children:"PrintStream throws UnsupportedEncodingException"}),"\n"]}),"\n",(0,r.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,r.jsx)(n.h3,{id:"allocation-of-jsonparser-and-cursor-resources",children:"Allocation of JSonParser and Cursor resources"}),"\n",(0,r.jsx)(n.p,{children:'Some resources are created inside libraries instead of by "new".'}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.h3,{id:"escaping-resources-and-exceptions",children:"Escaping resources and exceptions"}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["In this case it is intended that an object that wraps ",(0,r.jsx)(n.code,{children:"stream"})," is passed to the\ncaller of ",(0,r.jsx)(n.code,{children:"createAttachment"}),". You should certainly not close stream here,\nbecause it is being passed to the outside."]}),"\n",(0,r.jsx)(n.p,{children:"But for escaping resources like this you still need to be careful of exceptions.\nFor example, in"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.h3,{id:"java-7s-try-with-resources",children:"Java 7's try-with-resources"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"(For use with Java 7 only)"})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"All the complicated exceptional cases above are (apparently) covered by this\nconstruct, and the result is much simpler."}),"\n",(0,r.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,r.jsxs)(n.p,{children:["If try-with-resources is so great you should ",(0,r.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,r.jsx)(n.h2,{id:"retain_cycle",children:"RETAIN_CYCLE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"retain_cycle_no_weak_info",children:"RETAIN_CYCLE_NO_WEAK_INFO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Retain Cycle No Weak Info" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"scope_leakage",children:"SCOPE_LEAKAGE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Scope Leakage" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-scope-leakage",children:"scope-leakage"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"A configuration is used to list the set of scopes and the must-not-hold relation."}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.p,{children:"Here is a more detailed description of the analysis."}),"\n",(0,r.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,r.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,r.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,r.jsx)(n.h2,{id:"self_in_block_passed_to_init",children:"SELF_IN_BLOCK_PASSED_TO_INIT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#resource-leak",children:"Resource leak"}),'. Reported as "Self In Block Passed To Init" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check flags when ",(0,r.jsx)(n.code,{children:"self"})," is captured in a block that is passed to an initialiser method. That\ncould cause retain cycles if the initialiser code retains the block."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" [obj initWithHandler:^() {\n [self foo];\n ...\n }];\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Instead it's better to use the ",(0,r.jsx)(n.code,{children:"weakSelf"}),"/",(0,r.jsx)(n.code,{children:"strongSelf"})," pattern."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" __weak __typeof(self) weakSelf = self;\n [obj initWithHandler:^() {\n __strong __typeof(weakSelf) strongSelf = weakSelf;\n if (strongSelf) {\n [strongSelf foo];\n }\n ...\n }];\n"})}),"\n",(0,r.jsx)(n.h2,{id:"sensitive_data_flow",children:"SENSITIVE_DATA_FLOW"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Sensitive Data Flow" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A flow of sensitive data was detected from a source."}),"\n",(0,r.jsx)(n.h2,{id:"stack_variable_address_escape",children:"STACK_VARIABLE_ADDRESS_ESCAPE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Stack Variable Address Escape" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"For example, directly returning a pointer to a local variable:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"starvation",children:"STARVATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "UI Thread Starvation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"Infer considers a method as running on the UI thread whenever:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method, one of its overrides, its class, or an ancestral class, is\nannotated with ",(0,r.jsx)(n.code,{children:"@UiThread"}),"."]}),"\n",(0,r.jsxs)(n.li,{children:["The method, or one of its overrides is annotated with ",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnClick"}),",\netc."]}),"\n",(0,r.jsxs)(n.li,{children:["The method or its callees call a ",(0,r.jsx)(n.code,{children:"Litho.ThreadUtils"})," method such as\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The issue is reported when a method deemed to run on the UI thread"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Makes a method call which may block."}),"\n",(0,r.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,r.jsx)(n.p,{children:"Calls that may block are considered:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Certain I/O calls."}),"\n",(0,r.jsxs)(n.li,{children:["Two way ",(0,r.jsx)(n.code,{children:"Binder.transact"})," calls."]}),"\n",(0,r.jsx)(n.li,{children:"Certain OS calls."}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"Future"})," or ",(0,r.jsx)(n.code,{children:"AsyncTask"})," calls to ",(0,r.jsx)(n.code,{children:"get"})," without timeouts, or with too large\ntimeouts."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["To suppress starvation reports in a method ",(0,r.jsx)(n.code,{children:"m()"})," use the\n",(0,r.jsx)(n.code,{children:'@SuppressLint("STARVATION")'})," annotation, as follows:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-java",children:' import android.annotation.SuppressLint;\n\n @SuppressLint("STARVATION")\n public void m() {\n ...\n }\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To signal to Infer that a method does not perform any blocking calls, despite\nappearences, you can use the ",(0,r.jsx)(n.code,{children:"@NonBlocking"})," annotation:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:["This instructs Infer to filter out any potentially blocking calls in ",(0,r.jsx)(n.code,{children:"m()"}),"\n(also, transitively), and thus any other method can expect no starvation reports\ndue to a call to ",(0,r.jsx)(n.code,{children:"m()"}),". You will need to set up your class path appropriately to\ninclude the JAR files in ",(0,r.jsx)(n.code,{children:"infer/annotations"})," for this annotation to work."]}),"\n",(0,r.jsx)(n.h2,{id:"static_constructor_stall",children:"STATIC_CONSTRUCTOR_STALL"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Static Constructor Stall" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-static-constructor-stall-checker",children:"static-constructor-stall-checker"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"Calling certain methods, for instance dispatch_once, during the static initialization of objects is risky. It could cause deadlocks, because other objects might not have been initialized yet."}),"\n",(0,r.jsx)(n.h2,{id:"static_initialization_order_fiasco",children:"STATIC_INITIALIZATION_ORDER_FIASCO"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Static Initialization Order Fiasco" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-siof",children:"siof"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This error is reported in C++. It fires when the initialization of a static\nvariable ",(0,r.jsx)(n.code,{children:"A"}),", accesses a static variable ",(0,r.jsx)(n.code,{children:"B"})," from another translation unit\n(usually another ",(0,r.jsx)(n.code,{children:".cpp"})," file). There are no guarantees whether ",(0,r.jsx)(n.code,{children:"B"})," has been\nalready initialized or not at that point."]}),"\n",(0,r.jsxs)(n.p,{children:["For more technical definition and techniques to avoid/remediate, see the\n",(0,r.jsx)(n.a,{href:"https://isocpp.org/wiki/faq/ctors#static-init-order",children:"FAQ"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"strict_mode_violation",children:"STRICT_MODE_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#perf-regression",children:"Perf regression"}),'. Reported as "Strict Mode Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-starvation",children:"starvation"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["Android has a feature called\n",(0,r.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,r.jsx)(n.code,{children:"--starvation"})," analysis) has the\nability to statically detect such violations."]}),"\n",(0,r.jsxs)(n.p,{children:["To suppress this warning, it's enough to annotate the offending method with\n",(0,r.jsx)(n.code,{children:'@SuppressLint("STRICT_MODE_VIOLATION")'}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"strong_self_not_checked",children:"STRONG_SELF_NOT_CHECKED"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "StrongSelf Not Checked" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This checks reports a potential issue when a block captures ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.jsx)(n.code,{children:"self"}),"),\nthen one assigns this pointer to a local variable ",(0,r.jsx)(n.code,{children:"strongSelf"})," inside the block and uses this variable\nwithout checking first whether it is ",(0,r.jsx)(n.code,{children:"nil"}),". The problem here is that the weak pointer could be ",(0,r.jsx)(n.code,{children:"nil"})," at\nthe time when the block is executed. So, the correct usage is to first check whether ",(0,r.jsx)(n.code,{children:"strongSelf"})," is a valid\npointer, and then use it."]}),"\n",(0,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action:"}),"\nAdd a check for ",(0,r.jsx)(n.code,{children:"nil"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),".\nIn contrast, ",(0,r.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,r.jsx)(n.code,{children:"weakSelf"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"taint_error",children:"TAINT_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#sensitive-data-flow",children:"Sensitive data flow"}),'. Reported as "Taint Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsx)(n.p,{children:"A taint flow was detected from a source to a sink"}),"\n",(0,r.jsx)(n.h2,{id:"thread_safety_violation",children:"THREAD_SAFETY_VIOLATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#concurrency",children:"Concurrency"}),'. Reported as "Thread Safety Violation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"racerd"}),"."]})}),"\n",(0,r.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,r.jsx)(n.a,{href:"/docs/next/checker-racerd",children:"RacerD page"})," for more in-depth information and\nexamples."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-what-is-a-data-race",children:"Thread-safety: What is a data race"}),"\n",(0,r.jsx)(n.p,{children:"Here a data race is a pair of accesses to the same member field such that:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"at least one is a write, and,"}),"\n",(0,r.jsx)(n.li,{children:"at least one occurs without any lock synchronization, and,"}),"\n",(0,r.jsx)(n.li,{children:"the two accesses occur on threads (if known) which can run in parallel."}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-potential-fixes",children:"Thread-safety: Potential fixes"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Synchronizing the accesses (using the ",(0,r.jsx)(n.code,{children:"synchronized"})," keyword, thread-exclusion\nsuch as atomic objects, ",(0,r.jsx)(n.code,{children:"volatile"})," etc)."]}),"\n",(0,r.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,r.jsxs)(n.li,{children:["Putting the two accesses on the same thread, e.g., by using ",(0,r.jsx)(n.code,{children:"@MainThread"})," or\n",(0,r.jsx)(n.code,{children:"@ThreadConfined"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-conditions-checked-before-reporting",children:"Thread-safety: Conditions checked before reporting"}),"\n",(0,r.jsxs)(n.p,{children:["The class and method are not marked ",(0,r.jsx)(n.code,{children:"@ThreadSafe(enableChecks = false)"}),", and,"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The method is declared ",(0,r.jsx)(n.code,{children:"synchronized"}),", or employs (non-transitively) locking,\nor,"]}),"\n",(0,r.jsxs)(n.li,{children:["The class is not marked ",(0,r.jsx)(n.code,{children:"@NotThreadSafe"}),", and,","\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The class/method is marked ",(0,r.jsx)(n.code,{children:"@ThreadSafe,"})," or one of the configured synonyms\nin ",(0,r.jsx)(n.code,{children:".inferconfig"}),", or,"]}),"\n",(0,r.jsx)(n.li,{children:"A parent class, or an override method are marked with the above annotations."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["NB currently RacerD ",(0,r.jsxs)(n.strong,{children:["does not take into account ",(0,r.jsx)(n.code,{children:"@GuardedBy"})]}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-thread-annotations-recognized-by-racerd",children:"Thread-safety: Thread annotations recognized by RacerD"}),"\n",(0,r.jsxs)(n.p,{children:["These class and method annotations imply the method is on the main thread:\n",(0,r.jsx)(n.code,{children:"@MainThread"}),", ",(0,r.jsx)(n.code,{children:"@UiThread"})]}),"\n",(0,r.jsxs)(n.p,{children:["These method annotations imply the method is on the main thread: ",(0,r.jsx)(n.code,{children:"@OnBind"}),",\n",(0,r.jsx)(n.code,{children:"@OnEvent"}),", ",(0,r.jsx)(n.code,{children:"@OnMount"}),", ",(0,r.jsx)(n.code,{children:"@OnUnbind"}),", ",(0,r.jsx)(n.code,{children:"@OnUnmount"})]}),"\n",(0,r.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,r.jsxs)(n.p,{children:["In addition to these, RacerD recognizes many lifecycle methods as necessarily\nrunning on the main thread, eg ",(0,r.jsx)(n.code,{children:"Fragment.onCreate"})," etc."]}),"\n",(0,r.jsxs)(n.p,{children:["Finally, the thread status of being on the main thread propagates backwards\nthrough the call graph (ie if ",(0,r.jsx)(n.code,{children:"foo"})," calls ",(0,r.jsx)(n.code,{children:"bar"})," and ",(0,r.jsx)(n.code,{children:"bar"})," is marked ",(0,r.jsx)(n.code,{children:"@UiThtread"}),"\nthen ",(0,r.jsx)(n.code,{children:"foo"})," is automatically considered on the main thread too). Calling\n",(0,r.jsx)(n.code,{children:"assertMainThread"}),", ",(0,r.jsx)(n.code,{children:"assertOnUiThread"}),", ",(0,r.jsx)(n.code,{children:"checkOnMainThread"})," has the same effect."]}),"\n",(0,r.jsxs)(n.p,{children:["NB RacerD currently ",(0,r.jsxs)(n.strong,{children:["does not recognize ",(0,r.jsx)(n.code,{children:"@WorkerThread"}),", ",(0,r.jsx)(n.code,{children:"@BinderThread"})," or\n",(0,r.jsx)(n.code,{children:"@AnyThread"})]}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thread-safety-other-annotations-and-what-they-do",children:"Thread-safety: Other annotations and what they do"}),"\n",(0,r.jsxs)(n.p,{children:["These annotations can be found at ",(0,r.jsx)(n.code,{children:"com.facebook.infer.annotation.*"}),"."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@Functional"})," This is a method annotation indicating the method always returns\nthe same value. When a method ",(0,r.jsx)(n.code,{children:"foo"})," is annotated ",(0,r.jsx)(n.code,{children:"@Functional"}),", RacerD will\nignore any writes of the return value of ",(0,r.jsx)(n.code,{children:"foo"}),". For example, in\n",(0,r.jsx)(n.code,{children:"this.x = foo()"}),", the write to ",(0,r.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,r.jsx)(n.code,{children:"this.x"})," is benign, if that is the only write."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@ThreadConfined"})," This is a class/method/field annotation which takes a single\nparameter which can be ",(0,r.jsx)(n.code,{children:"UI"}),", ",(0,r.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,r.jsx)(n.code,{children:"@ThreadConfined(UI)"})," is equivalent to ",(0,r.jsx)(n.code,{children:"@UiThread"}),", and ",(0,r.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,r.jsx)(n.code,{children:"UI"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"@VisibleForTesting"})," A method annotation making Infer consider the method as\neffectively ",(0,r.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,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.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,r.jsx)(n.h2,{id:"topl_error",children:"TOPL_ERROR"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,r.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,r.jsx)(n.p,{children:"This indicates that the code has a user-defined undesired behavior."}),"\n",(0,r.jsxs)(n.p,{children:["See ",(0,r.jsx)(n.a,{href:"/docs/next/checker-topl#what-is-it",children:"Topl"})," for an example"]}),"\n",(0,r.jsx)(n.h2,{id:"topl_error_latent",children:"TOPL_ERROR_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#user-defined-property",children:"User defined property"}),'. Reported as "Topl Error Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-topl",children:"topl"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#topl_error",children:"TOPL_ERROR"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_delete",children:"USE_AFTER_DELETE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,r.jsx)(n.code,{children:"delete"})," in C++ is dereferenced."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_delete_latent",children:"USE_AFTER_DELETE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Delete Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_delete",children:"USE_AFTER_DELETE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_free",children:"USE_AFTER_FREE"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address that was invalidated by a call to ",(0,r.jsx)(n.code,{children:"free"})," in C is dereferenced."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_free_latent",children:"USE_AFTER_FREE_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Free Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_free",children:"USE_AFTER_FREE"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"use_after_lifetime",children:"USE_AFTER_LIFETIME"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.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,r.jsx)(n.pre,{children:(0,r.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,r.jsx)(n.h2,{id:"use_after_lifetime_latent",children:"USE_AFTER_LIFETIME_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Use After Lifetime Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#use_after_lifetime",children:"USE_AFTER_LIFETIME"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"vector_invalidation",children:"VECTOR_INVALIDATION"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["An address pointing into a C++ ",(0,r.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,r.jsx)(n.p,{children:"For example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-cpp",children:'void deref_vector_element_after_push_back_bad(std::vector& vec) {\n int* elt = &vec[1];\n int* y = elt;\n vec.push_back(42); // if the array backing the vector was full already, this\n // will re-allocate it and copy the previous contents\n // into the new array, then delete the previous array\n std::cout << *y << "\\n"; // bad: y might be invalid\n}\n'})}),"\n",(0,r.jsx)(n.h2,{id:"vector_invalidation_latent",children:"VECTOR_INVALIDATION_LATENT"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:["Category: ",(0,r.jsx)(n.a,{href:"/docs/next/all-categories#memory-error",children:"Memory error"}),'. Reported as "Vector Invalidation Latent" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse",children:"pulse"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["A latent ",(0,r.jsx)(n.a,{href:"#vector_invalidation",children:"VECTOR_INVALIDATION"}),". See the ",(0,r.jsx)(n.a,{href:"/docs/next/checker-pulse#latent-issues",children:"documentation on Pulse latent issues"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"weak_self_in_no_escape_block",children:"WEAK_SELF_IN_NO_ESCAPE_BLOCK"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.em,{children:['Reported as "Weak Self In No Escape Block" by ',(0,r.jsx)(n.a,{href:"/docs/next/checker-self-in-block",children:"self-in-block"}),"."]})}),"\n",(0,r.jsxs)(n.p,{children:["This check reports when ",(0,r.jsx)(n.code,{children:"weakSelf"})," (a weak pointer to ",(0,r.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,r.jsx)(n.code,{children:"NS_NOESCAPE"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:['The issue here is that, because the block is "no escaping", there is no need to use\n',(0,r.jsx)(n.code,{children:"weakSelf"})," and ",(0,r.jsx)(n.code,{children:"strongSelf"})," but we can just use ",(0,r.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,r.jsx)(n.p,{children:"Example:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.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,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Action"}),":"]}),"\n",(0,r.jsxs)(n.p,{children:["Replace ",(0,r.jsx)(n.code,{children:"weakSelf"})," with ",(0,r.jsx)(n.code,{children:"self"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-objectivec",children:" [self foo:^() {\n [self bar];\n }];\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.em,{children:"Limitations:"})," To keep this check simple and intra-procedural, we rely on names to find ",(0,r.jsx)(n.code,{children:"weakSelf"}),':\nwe assume that any captured weak pointer whose name contains "self" is a weak reference to ',(0,r.jsx)(n.code,{children:"self"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>l});var r=s(6540);const i={},t=r.createContext(i);function a(e){const n=r.useContext(t);return r.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(i):e.components||i:a(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/runtime~main.bf22b583.js b/assets/js/runtime~main.f2ef44c5.js
similarity index 97%
rename from assets/js/runtime~main.bf22b583.js
rename to assets/js/runtime~main.f2ef44c5.js
index 08f83ffd247..72dff7a6d74 100644
--- a/assets/js/runtime~main.bf22b583.js
+++ b/assets/js/runtime~main.f2ef44c5.js
@@ -1 +1 @@
-(()=>{"use strict";var a,e,f,c,d={},b={};function r(a){var e=b[a];if(void 0!==e)return e.exports;var f=b[a]={exports:{}};return d[a].call(f.exports,f,f.exports,r),f.exports}r.m=d,a=[],r.O=(e,f,c,d)=>{if(!f){var b=1/0;for(i=0;i=d)&&Object.keys(r.O).every((a=>r.O[a](f[o])))?f.splice(o--,1):(t=!1,d0&&a[i-1][2]>d;i--)a[i]=a[i-1];a[i]=[f,c,d]},r.n=a=>{var e=a&&a.__esModule?()=>a.default:()=>a;return r.d(e,{a:e}),e},f=Object.getPrototypeOf?a=>Object.getPrototypeOf(a):a=>a.__proto__,r.t=function(a,c){if(1&c&&(a=this(a)),8&c)return a;if("object"==typeof a&&a){if(4&c&&a.__esModule)return a;if(16&c&&"function"==typeof a.then)return a}var d=Object.create(null);r.r(d);var b={};e=e||[null,f({}),f([]),f(f)];for(var t=2&c&&a;"object"==typeof t&&!~e.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((e=>b[e]=()=>a[e]));return b.default=()=>a,r.d(d,b),d},r.d=(a,e)=>{for(var f in e)r.o(e,f)&&!r.o(a,f)&&Object.defineProperty(a,f,{enumerable:!0,get:e[f]})},r.f={},r.e=a=>Promise.all(Object.keys(r.f).reduce(((e,f)=>(r.f[f](a,e),e)),[])),r.u=a=>"assets/js/"+({46:"b05ccea0",100:"57bcddd6",293:"ac4b567d",411:"7f661f82",457:"4cccfac9",468:"34fbd09a",485:"7b1f0035",492:"61eca9d6",517:"f8092feb",530:"58972da3",553:"a373fd77",613:"acaf655c",659:"3c055f5e",700:"5aef2ce6",741:"3423820d",777:"56ebd09a",849:"0058b4c6",881:"71a2656f",946:"884bd1d2",957:"c141421f",1010:"aa0b35eb",1068:"bbdc39ec",1158:"8919ea97",1235:"a7456010",1236:"e436f9fb",1279:"21a9d6ed",1410:"a8248417",1416:"d9e16301",1439:"c8131338",1444:"9d221b96",1463:"be77d225",1533:"33776668",1599:"abc9d724",1610:"b9f8aa82",1652:"6297ff83",1734:"a33b6a74",1759:"89b1f439",1822:"4dac5fec",1847:"f28f39ea",1903:"acecf23e",1926:"3eb0a99f",1932:"7a64ca81",1989:"a5a260f1",1998:"06d8773d",2032:"21614072",2057:"cd3b4295",2138:"1a4e3797",2212:"bf6aacca",2316:"c359af60",2365:"ae894706",2380:"ae565638",2385:"e44e3f47",2509:"6d752ef5",2634:"c4f5d8e4",2708:"9d4bdb35",2711:"9e4087bc",2740:"65dc7644",2883:"8a838ea0",2938:"d47ba782",2968:"a02168a2",2996:"8a061d83",3157:"3c653e3b",3212:"76c96f4d",3249:"ccc49370",3426:"9258f162",3487:"7b6b5c72",3526:"4c2546f9",3548:"6021085e",3699:"1772b9c1",3716:"eb0c92c1",3730:"70793eb2",3838:"a67edc69",3967:"5a5dcc21",4215:"3a27b2d9",4235:"00d3276d",4261:"5bb07cf5",4341:"e0f83a1d",4478:"8fb47bcc",4515:"937dc5a6",4569:"e6b9ef91",4631:"a2bed8f0",4638:"bd470307",4721:"812c592f",4728:"671939c9",4765:"c412bf64",4865:"79263788",4883:"491a3217",4982:"e9325e77",5041:"5573af76",5073:"fd7416f6",5075:"c8a5dae5",5118:"bf769997",5277:"0346afaa",5360:"420497a2",5386:"3c741b47",5543:"81cc3644",5632:"1d8647da",5680:"7efbfa7e",5742:"aba21aa0",6096:"25a5a20c",6107:"16fe8a4c",6112:"f22cd6c1",6146:"da41ed28",6166:"57dd985e",6227:"3a3b1bdb",6230:"38f5dda4",6231:"293e08e8",6237:"f5ff54f0",6241:"509dc7bf",6408:"aaff9110",6499:"b4a56aa4",6510:"fa38ac94",6555:"b388a56e",6629:"64f1f19c",6689:"58de4400",6929:"fa9ab54d",6950:"0c0efcaa",7017:"ca86781b",7098:"a7bd4aaa",7197:"5f403532",7207:"00e87d9a",7211:"0774da3f",7283:"a3e198d1",7314:"1df9637e",7318:"4b970726",7323:"7f18f0db",7331:"136023f9",7343:"1ed7bad6",7378:"04f8d6af",7417:"637f8365",7419:"ab17452f",7436:"bc20efef",7472:"814f3328",7560:"bab022f4",7586:"45d37095",7632:"b065408b",7643:"a6aa9e1f",7698:"cd83de9e",7709:"64cca8ef",7758:"f28ca027",7773:"184ad633",7803:"df12ff2a",7877:"3eac2097",7906:"f769b3fd",7930:"7dd0d394",7972:"acb2d06a",8045:"041e4035",8108:"aaa764ed",8112:"bc3f1a98",8130:"f81c1134",8146:"c15d9823",8283:"37d3b766",8301:"4f53e586",8401:"17896441",8405:"5acb8db5",8500:"e66621bc",8680:"3d9729af",8684:"c26add1d",8822:"3f2a1ecb",8886:"413f2abb",8973:"1dbe42a7",8984:"99c7964b",9023:"1fdfdeaa",9026:"5c708541",9034:"b7bf8e49",9048:"a94703ab",9088:"18328e9e",9095:"cf554d4e",9262:"d1458f14",9366:"0fe8a02a",9383:"223037ba",9390:"c222a988",9401:"a177ae00",9420:"0c78c462",9437:"8fdeae25",9525:"bf1307fc",9640:"9702a600",9647:"5e95c892",9676:"e305a15c",9677:"556d04db",9692:"1906a68b",9749:"8db808e7",9820:"4fb08289",9858:"36994c47",9978:"1c7a9c9f"}[a]||a)+"."+{46:"b2cb9ba6",100:"7e504885",293:"d04b5583",411:"9f54fe23",416:"b444750d",457:"10781a2e",468:"0b6da666",485:"84560a9e",492:"27add587",517:"45da7e6b",530:"144b1897",553:"cd1fb531",613:"eb6448cb",659:"c9fee1c3",700:"60ce27e3",741:"ea770bb6",777:"0c8134d7",849:"e2f8f141",881:"22df8c25",946:"c3a6acde",957:"9a903d38",1010:"f4ed61f6",1068:"43afbcfd",1158:"7896e2fd",1235:"7e3226f2",1236:"d2432c58",1279:"80187f24",1410:"f12afd1b",1416:"99a75473",1439:"a2fef71a",1444:"8b4ff73f",1463:"b6366ec4",1533:"1e84a12d",1599:"433f01d0",1610:"26b69d02",1652:"ac2d38d7",1734:"bc321def",1759:"5b60b603",1822:"b053f13c",1847:"a016e3c4",1903:"3eef8a98",1926:"3c9f37cb",1932:"c274d3ab",1989:"f642cec3",1998:"399aff17",2032:"6066b791",2057:"4e2f5182",2138:"9a1f1807",2212:"35ad86e9",2237:"fdb00234",2316:"1278ce61",2365:"81c60e92",2380:"6ab36f60",2385:"75eba3eb",2509:"0bd22b04",2634:"25763f5c",2708:"40b0336b",2711:"1081de11",2740:"c4295ab5",2883:"d4259207",2938:"ad0784b3",2968:"c12dfb67",2996:"a2812d5a",3157:"1a485114",3212:"569557e5",3249:"28189709",3426:"6f760b9c",3487:"455be240",3526:"d30dc19e",3548:"d9150b94",3699:"6bf2e57d",3716:"4e7df13b",3730:"22f027bd",3838:"1001aa09",3962:"52e2266e",3967:"693ecffd",4215:"c7e85dcd",4235:"cad11f73",4261:"20d299eb",4341:"4b69d034",4478:"84c3c61a",4515:"32551d95",4569:"ec74b673",4631:"363bd2ea",4638:"0413a1ba",4721:"aff6270b",4728:"f5aac289",4765:"8ff827fe",4865:"d5a31d4b",4883:"d4d1ae39",4982:"2a9e7126",5041:"568cdecb",5073:"4ae8f342",5075:"a0ba9bb5",5118:"1fa7cc3d",5277:"b3c3fd48",5360:"2011b81d",5386:"96e959b4",5543:"ccae926e",5632:"c432d9e3",5680:"e65a1f00",5742:"0aa4e8d5",6096:"e78589bb",6107:"0eb550b3",6112:"49c4901a",6146:"6c1a90fd",6166:"a29cb4d7",6227:"518da510",6230:"cedc7aba",6231:"c6941bee",6237:"4ca96c24",6238:"29a1b222",6241:"6a3d89bc",6408:"11519136",6499:"f86e56c3",6510:"410e9623",6555:"c99fd548",6629:"872a0fc0",6689:"8585eca6",6929:"96176fab",6950:"c5f5b6c5",7017:"20ee549e",7098:"664e8c83",7197:"bba25bff",7207:"ef765681",7211:"61723255",7283:"10f69968",7314:"d3e87582",7318:"32fb9336",7323:"27c4044f",7331:"7d417834",7343:"c6e0943c",7378:"c08c57a3",7417:"91ff7f1a",7419:"ae848db9",7436:"283b9ce1",7472:"7a062e80",7560:"6084716d",7586:"9862a2cf",7632:"a20f5cc6",7643:"6b9a26f5",7698:"beb22e5d",7709:"a45faa55",7758:"0b9ad65b",7773:"240342b6",7803:"4d76c75b",7877:"2a2c61e7",7906:"795aa392",7930:"6924f01e",7972:"2a6a82d3",8045:"b69a3096",8108:"15e2a19c",8112:"f88f3e24",8130:"cc174e15",8146:"047496b9",8158:"cfa83e34",8283:"0b0d66d2",8301:"a5671cc6",8401:"0f17bec8",8405:"12015b5c",8500:"c5f2ec17",8680:"df738802",8684:"d8ca081e",8822:"dfb31018",8886:"2a3134f2",8913:"b6f04e6e",8973:"ac57b1d6",8984:"ef715b7b",9023:"678fc887",9026:"6ca14753",9034:"fe974b18",9048:"15908900",9088:"b1d20ec4",9095:"32b19eb1",9262:"a7b41027",9366:"4fdeaedd",9383:"2aa7902c",9390:"f2ba5f8b",9401:"6bc20c68",9420:"88d0615d",9437:"904d52c1",9525:"a6567380",9640:"b1b54438",9647:"b2f2604d",9676:"9f747501",9677:"d65448fc",9692:"f6bbe8eb",9749:"940e50fa",9820:"c072ae0c",9858:"72bbc0ce",9978:"dee77249"}[a]+".js",r.miniCssF=a=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(a){if("object"==typeof window)return window}}(),r.o=(a,e)=>Object.prototype.hasOwnProperty.call(a,e),c={},r.l=(a,e,f,d)=>{if(c[a])c[a].push(e);else{var b,t;if(void 0!==f)for(var o=document.getElementsByTagName("script"),n=0;n{b.onerror=b.onload=null,clearTimeout(l);var d=c[a];if(delete c[a],b.parentNode&&b.parentNode.removeChild(b),d&&d.forEach((a=>a(f))),e)return e(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=u.bind(null,b.onerror),b.onload=u.bind(null,b.onload),t&&document.head.appendChild(b)}},r.r=a=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},r.p="/",r.gca=function(a){return a={17896441:"8401",21614072:"2032",33776668:"1533",79263788:"4865",b05ccea0:"46","57bcddd6":"100",ac4b567d:"293","7f661f82":"411","4cccfac9":"457","34fbd09a":"468","7b1f0035":"485","61eca9d6":"492",f8092feb:"517","58972da3":"530",a373fd77:"553",acaf655c:"613","3c055f5e":"659","5aef2ce6":"700","3423820d":"741","56ebd09a":"777","0058b4c6":"849","71a2656f":"881","884bd1d2":"946",c141421f:"957",aa0b35eb:"1010",bbdc39ec:"1068","8919ea97":"1158",a7456010:"1235",e436f9fb:"1236","21a9d6ed":"1279",a8248417:"1410",d9e16301:"1416",c8131338:"1439","9d221b96":"1444",be77d225:"1463",abc9d724:"1599",b9f8aa82:"1610","6297ff83":"1652",a33b6a74:"1734","89b1f439":"1759","4dac5fec":"1822",f28f39ea:"1847",acecf23e:"1903","3eb0a99f":"1926","7a64ca81":"1932",a5a260f1:"1989","06d8773d":"1998",cd3b4295:"2057","1a4e3797":"2138",bf6aacca:"2212",c359af60:"2316",ae894706:"2365",ae565638:"2380",e44e3f47:"2385","6d752ef5":"2509",c4f5d8e4:"2634","9d4bdb35":"2708","9e4087bc":"2711","65dc7644":"2740","8a838ea0":"2883",d47ba782:"2938",a02168a2:"2968","8a061d83":"2996","3c653e3b":"3157","76c96f4d":"3212",ccc49370:"3249","9258f162":"3426","7b6b5c72":"3487","4c2546f9":"3526","6021085e":"3548","1772b9c1":"3699",eb0c92c1:"3716","70793eb2":"3730",a67edc69:"3838","5a5dcc21":"3967","3a27b2d9":"4215","00d3276d":"4235","5bb07cf5":"4261",e0f83a1d:"4341","8fb47bcc":"4478","937dc5a6":"4515",e6b9ef91:"4569",a2bed8f0:"4631",bd470307:"4638","812c592f":"4721","671939c9":"4728",c412bf64:"4765","491a3217":"4883",e9325e77:"4982","5573af76":"5041",fd7416f6:"5073",c8a5dae5:"5075",bf769997:"5118","0346afaa":"5277","420497a2":"5360","3c741b47":"5386","81cc3644":"5543","1d8647da":"5632","7efbfa7e":"5680",aba21aa0:"5742","25a5a20c":"6096","16fe8a4c":"6107",f22cd6c1:"6112",da41ed28:"6146","57dd985e":"6166","3a3b1bdb":"6227","38f5dda4":"6230","293e08e8":"6231",f5ff54f0:"6237","509dc7bf":"6241",aaff9110:"6408",b4a56aa4:"6499",fa38ac94:"6510",b388a56e:"6555","64f1f19c":"6629","58de4400":"6689",fa9ab54d:"6929","0c0efcaa":"6950",ca86781b:"7017",a7bd4aaa:"7098","5f403532":"7197","00e87d9a":"7207","0774da3f":"7211",a3e198d1:"7283","1df9637e":"7314","4b970726":"7318","7f18f0db":"7323","136023f9":"7331","1ed7bad6":"7343","04f8d6af":"7378","637f8365":"7417",ab17452f:"7419",bc20efef:"7436","814f3328":"7472",bab022f4:"7560","45d37095":"7586",b065408b:"7632",a6aa9e1f:"7643",cd83de9e:"7698","64cca8ef":"7709",f28ca027:"7758","184ad633":"7773",df12ff2a:"7803","3eac2097":"7877",f769b3fd:"7906","7dd0d394":"7930",acb2d06a:"7972","041e4035":"8045",aaa764ed:"8108",bc3f1a98:"8112",f81c1134:"8130",c15d9823:"8146","37d3b766":"8283","4f53e586":"8301","5acb8db5":"8405",e66621bc:"8500","3d9729af":"8680",c26add1d:"8684","3f2a1ecb":"8822","413f2abb":"8886","1dbe42a7":"8973","99c7964b":"8984","1fdfdeaa":"9023","5c708541":"9026",b7bf8e49:"9034",a94703ab:"9048","18328e9e":"9088",cf554d4e:"9095",d1458f14:"9262","0fe8a02a":"9366","223037ba":"9383",c222a988:"9390",a177ae00:"9401","0c78c462":"9420","8fdeae25":"9437",bf1307fc:"9525","9702a600":"9640","5e95c892":"9647",e305a15c:"9676","556d04db":"9677","1906a68b":"9692","8db808e7":"9749","4fb08289":"9820","36994c47":"9858","1c7a9c9f":"9978"}[a]||a,r.p+r.u(a)},(()=>{var a={5354:0,1869:0};r.f.j=(e,f)=>{var c=r.o(a,e)?a[e]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1869|5354)$/.test(e))a[e]=0;else{var d=new Promise(((f,d)=>c=a[e]=[f,d]));f.push(c[2]=d);var b=r.p+r.u(e),t=new Error;r.l(b,(f=>{if(r.o(a,e)&&(0!==(c=a[e])&&(a[e]=void 0),c)){var d=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+e+" failed.\n("+d+": "+b+")",t.name="ChunkLoadError",t.type=d,t.request=b,c[1](t)}}),"chunk-"+e,e)}},r.O.j=e=>0===a[e];var e=(e,f)=>{var c,d,b=f[0],t=f[1],o=f[2],n=0;if(b.some((e=>0!==a[e]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(e&&e(f);n{"use strict";var a,e,f,c,d={},b={};function r(a){var e=b[a];if(void 0!==e)return e.exports;var f=b[a]={exports:{}};return d[a].call(f.exports,f,f.exports,r),f.exports}r.m=d,a=[],r.O=(e,f,c,d)=>{if(!f){var b=1/0;for(i=0;i=d)&&Object.keys(r.O).every((a=>r.O[a](f[o])))?f.splice(o--,1):(t=!1,d0&&a[i-1][2]>d;i--)a[i]=a[i-1];a[i]=[f,c,d]},r.n=a=>{var e=a&&a.__esModule?()=>a.default:()=>a;return r.d(e,{a:e}),e},f=Object.getPrototypeOf?a=>Object.getPrototypeOf(a):a=>a.__proto__,r.t=function(a,c){if(1&c&&(a=this(a)),8&c)return a;if("object"==typeof a&&a){if(4&c&&a.__esModule)return a;if(16&c&&"function"==typeof a.then)return a}var d=Object.create(null);r.r(d);var b={};e=e||[null,f({}),f([]),f(f)];for(var t=2&c&&a;"object"==typeof t&&!~e.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((e=>b[e]=()=>a[e]));return b.default=()=>a,r.d(d,b),d},r.d=(a,e)=>{for(var f in e)r.o(e,f)&&!r.o(a,f)&&Object.defineProperty(a,f,{enumerable:!0,get:e[f]})},r.f={},r.e=a=>Promise.all(Object.keys(r.f).reduce(((e,f)=>(r.f[f](a,e),e)),[])),r.u=a=>"assets/js/"+({46:"b05ccea0",100:"57bcddd6",293:"ac4b567d",411:"7f661f82",457:"4cccfac9",468:"34fbd09a",485:"7b1f0035",492:"61eca9d6",517:"f8092feb",530:"58972da3",553:"a373fd77",613:"acaf655c",659:"3c055f5e",700:"5aef2ce6",741:"3423820d",777:"56ebd09a",849:"0058b4c6",881:"71a2656f",946:"884bd1d2",957:"c141421f",1010:"aa0b35eb",1068:"bbdc39ec",1158:"8919ea97",1235:"a7456010",1236:"e436f9fb",1279:"21a9d6ed",1410:"a8248417",1416:"d9e16301",1439:"c8131338",1444:"9d221b96",1463:"be77d225",1533:"33776668",1599:"abc9d724",1610:"b9f8aa82",1652:"6297ff83",1734:"a33b6a74",1759:"89b1f439",1822:"4dac5fec",1847:"f28f39ea",1903:"acecf23e",1926:"3eb0a99f",1932:"7a64ca81",1989:"a5a260f1",1998:"06d8773d",2032:"21614072",2057:"cd3b4295",2138:"1a4e3797",2212:"bf6aacca",2316:"c359af60",2365:"ae894706",2380:"ae565638",2385:"e44e3f47",2509:"6d752ef5",2634:"c4f5d8e4",2708:"9d4bdb35",2711:"9e4087bc",2740:"65dc7644",2883:"8a838ea0",2938:"d47ba782",2968:"a02168a2",2996:"8a061d83",3157:"3c653e3b",3212:"76c96f4d",3249:"ccc49370",3426:"9258f162",3487:"7b6b5c72",3526:"4c2546f9",3548:"6021085e",3699:"1772b9c1",3716:"eb0c92c1",3730:"70793eb2",3838:"a67edc69",3967:"5a5dcc21",4215:"3a27b2d9",4235:"00d3276d",4261:"5bb07cf5",4341:"e0f83a1d",4478:"8fb47bcc",4515:"937dc5a6",4569:"e6b9ef91",4631:"a2bed8f0",4638:"bd470307",4721:"812c592f",4728:"671939c9",4765:"c412bf64",4865:"79263788",4883:"491a3217",4982:"e9325e77",5041:"5573af76",5073:"fd7416f6",5075:"c8a5dae5",5118:"bf769997",5277:"0346afaa",5360:"420497a2",5386:"3c741b47",5543:"81cc3644",5632:"1d8647da",5680:"7efbfa7e",5742:"aba21aa0",6096:"25a5a20c",6107:"16fe8a4c",6112:"f22cd6c1",6146:"da41ed28",6166:"57dd985e",6227:"3a3b1bdb",6230:"38f5dda4",6231:"293e08e8",6237:"f5ff54f0",6241:"509dc7bf",6408:"aaff9110",6499:"b4a56aa4",6510:"fa38ac94",6555:"b388a56e",6629:"64f1f19c",6689:"58de4400",6929:"fa9ab54d",6950:"0c0efcaa",7017:"ca86781b",7098:"a7bd4aaa",7197:"5f403532",7207:"00e87d9a",7211:"0774da3f",7283:"a3e198d1",7314:"1df9637e",7318:"4b970726",7323:"7f18f0db",7331:"136023f9",7343:"1ed7bad6",7378:"04f8d6af",7417:"637f8365",7419:"ab17452f",7436:"bc20efef",7472:"814f3328",7560:"bab022f4",7586:"45d37095",7632:"b065408b",7643:"a6aa9e1f",7698:"cd83de9e",7709:"64cca8ef",7758:"f28ca027",7773:"184ad633",7803:"df12ff2a",7877:"3eac2097",7906:"f769b3fd",7930:"7dd0d394",7972:"acb2d06a",8045:"041e4035",8108:"aaa764ed",8112:"bc3f1a98",8130:"f81c1134",8146:"c15d9823",8283:"37d3b766",8301:"4f53e586",8401:"17896441",8405:"5acb8db5",8500:"e66621bc",8680:"3d9729af",8684:"c26add1d",8822:"3f2a1ecb",8886:"413f2abb",8973:"1dbe42a7",8984:"99c7964b",9023:"1fdfdeaa",9026:"5c708541",9034:"b7bf8e49",9048:"a94703ab",9088:"18328e9e",9095:"cf554d4e",9262:"d1458f14",9366:"0fe8a02a",9383:"223037ba",9390:"c222a988",9401:"a177ae00",9420:"0c78c462",9437:"8fdeae25",9525:"bf1307fc",9640:"9702a600",9647:"5e95c892",9676:"e305a15c",9677:"556d04db",9692:"1906a68b",9749:"8db808e7",9820:"4fb08289",9858:"36994c47",9978:"1c7a9c9f"}[a]||a)+"."+{46:"b2cb9ba6",100:"7e504885",293:"d04b5583",411:"9f54fe23",416:"b444750d",457:"10781a2e",468:"0b6da666",485:"84560a9e",492:"27add587",517:"45da7e6b",530:"144b1897",553:"cd1fb531",613:"eb6448cb",659:"c9fee1c3",700:"60ce27e3",741:"ea770bb6",777:"0c8134d7",849:"e2f8f141",881:"22df8c25",946:"c3a6acde",957:"9a903d38",1010:"f4ed61f6",1068:"43afbcfd",1158:"7896e2fd",1235:"7e3226f2",1236:"d2432c58",1279:"80187f24",1410:"f12afd1b",1416:"99a75473",1439:"a2fef71a",1444:"8b4ff73f",1463:"b6366ec4",1533:"1e84a12d",1599:"433f01d0",1610:"26b69d02",1652:"ac2d38d7",1734:"bc321def",1759:"5b60b603",1822:"b053f13c",1847:"a016e3c4",1903:"3eef8a98",1926:"3c9f37cb",1932:"c274d3ab",1989:"f642cec3",1998:"399aff17",2032:"6066b791",2057:"4e2f5182",2138:"9a1f1807",2212:"35ad86e9",2237:"fdb00234",2316:"87765c92",2365:"81c60e92",2380:"6ab36f60",2385:"75eba3eb",2509:"0bd22b04",2634:"25763f5c",2708:"40b0336b",2711:"1081de11",2740:"c4295ab5",2883:"d4259207",2938:"ad0784b3",2968:"c12dfb67",2996:"a2812d5a",3157:"1a485114",3212:"569557e5",3249:"28189709",3426:"6f760b9c",3487:"455be240",3526:"d30dc19e",3548:"d9150b94",3699:"6bf2e57d",3716:"4e7df13b",3730:"22f027bd",3838:"1001aa09",3962:"52e2266e",3967:"693ecffd",4215:"c7e85dcd",4235:"cad11f73",4261:"20d299eb",4341:"4b69d034",4478:"84c3c61a",4515:"32551d95",4569:"ec74b673",4631:"363bd2ea",4638:"0413a1ba",4721:"aff6270b",4728:"f5aac289",4765:"8ff827fe",4865:"d5a31d4b",4883:"d4d1ae39",4982:"2a9e7126",5041:"568cdecb",5073:"4ae8f342",5075:"a0ba9bb5",5118:"1fa7cc3d",5277:"b3c3fd48",5360:"2011b81d",5386:"96e959b4",5543:"ccae926e",5632:"c432d9e3",5680:"e65a1f00",5742:"0aa4e8d5",6096:"e78589bb",6107:"0eb550b3",6112:"49c4901a",6146:"6c1a90fd",6166:"a29cb4d7",6227:"518da510",6230:"cedc7aba",6231:"c6941bee",6237:"4ca96c24",6238:"29a1b222",6241:"6a3d89bc",6408:"11519136",6499:"f86e56c3",6510:"410e9623",6555:"c99fd548",6629:"872a0fc0",6689:"8585eca6",6929:"96176fab",6950:"c5f5b6c5",7017:"20ee549e",7098:"664e8c83",7197:"bba25bff",7207:"ef765681",7211:"61723255",7283:"10f69968",7314:"d3e87582",7318:"32fb9336",7323:"27c4044f",7331:"7d417834",7343:"c6e0943c",7378:"c08c57a3",7417:"91ff7f1a",7419:"ae848db9",7436:"283b9ce1",7472:"7a062e80",7560:"6084716d",7586:"9862a2cf",7632:"a20f5cc6",7643:"6b9a26f5",7698:"beb22e5d",7709:"a45faa55",7758:"0b9ad65b",7773:"240342b6",7803:"4d76c75b",7877:"2a2c61e7",7906:"795aa392",7930:"6924f01e",7972:"2a6a82d3",8045:"e204036c",8108:"15e2a19c",8112:"f88f3e24",8130:"cc174e15",8146:"047496b9",8158:"cfa83e34",8283:"0b0d66d2",8301:"a5671cc6",8401:"0f17bec8",8405:"12015b5c",8500:"c5f2ec17",8680:"df738802",8684:"d8ca081e",8822:"dfb31018",8886:"2a3134f2",8913:"b6f04e6e",8973:"ac57b1d6",8984:"ef715b7b",9023:"678fc887",9026:"6ca14753",9034:"fe974b18",9048:"15908900",9088:"b1d20ec4",9095:"32b19eb1",9262:"a7b41027",9366:"4fdeaedd",9383:"890494e4",9390:"f2ba5f8b",9401:"6bc20c68",9420:"88d0615d",9437:"5a49904a",9525:"a6567380",9640:"b1b54438",9647:"b2f2604d",9676:"9f747501",9677:"d65448fc",9692:"f6bbe8eb",9749:"940e50fa",9820:"c072ae0c",9858:"72bbc0ce",9978:"dee77249"}[a]+".js",r.miniCssF=a=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(a){if("object"==typeof window)return window}}(),r.o=(a,e)=>Object.prototype.hasOwnProperty.call(a,e),c={},r.l=(a,e,f,d)=>{if(c[a])c[a].push(e);else{var b,t;if(void 0!==f)for(var o=document.getElementsByTagName("script"),n=0;n{b.onerror=b.onload=null,clearTimeout(l);var d=c[a];if(delete c[a],b.parentNode&&b.parentNode.removeChild(b),d&&d.forEach((a=>a(f))),e)return e(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=u.bind(null,b.onerror),b.onload=u.bind(null,b.onload),t&&document.head.appendChild(b)}},r.r=a=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})},r.p="/",r.gca=function(a){return a={17896441:"8401",21614072:"2032",33776668:"1533",79263788:"4865",b05ccea0:"46","57bcddd6":"100",ac4b567d:"293","7f661f82":"411","4cccfac9":"457","34fbd09a":"468","7b1f0035":"485","61eca9d6":"492",f8092feb:"517","58972da3":"530",a373fd77:"553",acaf655c:"613","3c055f5e":"659","5aef2ce6":"700","3423820d":"741","56ebd09a":"777","0058b4c6":"849","71a2656f":"881","884bd1d2":"946",c141421f:"957",aa0b35eb:"1010",bbdc39ec:"1068","8919ea97":"1158",a7456010:"1235",e436f9fb:"1236","21a9d6ed":"1279",a8248417:"1410",d9e16301:"1416",c8131338:"1439","9d221b96":"1444",be77d225:"1463",abc9d724:"1599",b9f8aa82:"1610","6297ff83":"1652",a33b6a74:"1734","89b1f439":"1759","4dac5fec":"1822",f28f39ea:"1847",acecf23e:"1903","3eb0a99f":"1926","7a64ca81":"1932",a5a260f1:"1989","06d8773d":"1998",cd3b4295:"2057","1a4e3797":"2138",bf6aacca:"2212",c359af60:"2316",ae894706:"2365",ae565638:"2380",e44e3f47:"2385","6d752ef5":"2509",c4f5d8e4:"2634","9d4bdb35":"2708","9e4087bc":"2711","65dc7644":"2740","8a838ea0":"2883",d47ba782:"2938",a02168a2:"2968","8a061d83":"2996","3c653e3b":"3157","76c96f4d":"3212",ccc49370:"3249","9258f162":"3426","7b6b5c72":"3487","4c2546f9":"3526","6021085e":"3548","1772b9c1":"3699",eb0c92c1:"3716","70793eb2":"3730",a67edc69:"3838","5a5dcc21":"3967","3a27b2d9":"4215","00d3276d":"4235","5bb07cf5":"4261",e0f83a1d:"4341","8fb47bcc":"4478","937dc5a6":"4515",e6b9ef91:"4569",a2bed8f0:"4631",bd470307:"4638","812c592f":"4721","671939c9":"4728",c412bf64:"4765","491a3217":"4883",e9325e77:"4982","5573af76":"5041",fd7416f6:"5073",c8a5dae5:"5075",bf769997:"5118","0346afaa":"5277","420497a2":"5360","3c741b47":"5386","81cc3644":"5543","1d8647da":"5632","7efbfa7e":"5680",aba21aa0:"5742","25a5a20c":"6096","16fe8a4c":"6107",f22cd6c1:"6112",da41ed28:"6146","57dd985e":"6166","3a3b1bdb":"6227","38f5dda4":"6230","293e08e8":"6231",f5ff54f0:"6237","509dc7bf":"6241",aaff9110:"6408",b4a56aa4:"6499",fa38ac94:"6510",b388a56e:"6555","64f1f19c":"6629","58de4400":"6689",fa9ab54d:"6929","0c0efcaa":"6950",ca86781b:"7017",a7bd4aaa:"7098","5f403532":"7197","00e87d9a":"7207","0774da3f":"7211",a3e198d1:"7283","1df9637e":"7314","4b970726":"7318","7f18f0db":"7323","136023f9":"7331","1ed7bad6":"7343","04f8d6af":"7378","637f8365":"7417",ab17452f:"7419",bc20efef:"7436","814f3328":"7472",bab022f4:"7560","45d37095":"7586",b065408b:"7632",a6aa9e1f:"7643",cd83de9e:"7698","64cca8ef":"7709",f28ca027:"7758","184ad633":"7773",df12ff2a:"7803","3eac2097":"7877",f769b3fd:"7906","7dd0d394":"7930",acb2d06a:"7972","041e4035":"8045",aaa764ed:"8108",bc3f1a98:"8112",f81c1134:"8130",c15d9823:"8146","37d3b766":"8283","4f53e586":"8301","5acb8db5":"8405",e66621bc:"8500","3d9729af":"8680",c26add1d:"8684","3f2a1ecb":"8822","413f2abb":"8886","1dbe42a7":"8973","99c7964b":"8984","1fdfdeaa":"9023","5c708541":"9026",b7bf8e49:"9034",a94703ab:"9048","18328e9e":"9088",cf554d4e:"9095",d1458f14:"9262","0fe8a02a":"9366","223037ba":"9383",c222a988:"9390",a177ae00:"9401","0c78c462":"9420","8fdeae25":"9437",bf1307fc:"9525","9702a600":"9640","5e95c892":"9647",e305a15c:"9676","556d04db":"9677","1906a68b":"9692","8db808e7":"9749","4fb08289":"9820","36994c47":"9858","1c7a9c9f":"9978"}[a]||a,r.p+r.u(a)},(()=>{var a={5354:0,1869:0};r.f.j=(e,f)=>{var c=r.o(a,e)?a[e]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1869|5354)$/.test(e))a[e]=0;else{var d=new Promise(((f,d)=>c=a[e]=[f,d]));f.push(c[2]=d);var b=r.p+r.u(e),t=new Error;r.l(b,(f=>{if(r.o(a,e)&&(0!==(c=a[e])&&(a[e]=void 0),c)){var d=f&&("load"===f.type?"missing":f.type),b=f&&f.target&&f.target.src;t.message="Loading chunk "+e+" failed.\n("+d+": "+b+")",t.name="ChunkLoadError",t.type=d,t.request=b,c[1](t)}}),"chunk-"+e,e)}},r.O.j=e=>0===a[e];var e=(e,f)=>{var c,d,b=f[0],t=f[1],o=f[2],n=0;if(b.some((e=>0!==a[e]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(e&&e(f);n
-
+
diff --git a/blog/2016/03/17/collaboration-with-spotify/index.html b/blog/2016/03/17/collaboration-with-spotify/index.html
index 27e2314fa11..46d8c1e7a18 100644
--- a/blog/2016/03/17/collaboration-with-spotify/index.html
+++ b/blog/2016/03/17/collaboration-with-spotify/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/2016/04/07/mobileatscale-london-talk/index.html b/blog/2016/04/07/mobileatscale-london-talk/index.html
index 807db2c91fb..bb637394a87 100644
--- a/blog/2016/04/07/mobileatscale-london-talk/index.html
+++ b/blog/2016/04/07/mobileatscale-london-talk/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/2016/06/23/first-opensourceversary/index.html b/blog/2016/06/23/first-opensourceversary/index.html
index a1fb17aedec..4c0cfd578a4 100644
--- a/blog/2016/06/23/first-opensourceversary/index.html
+++ b/blog/2016/06/23/first-opensourceversary/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/2016/08/30/curryon-rome-talk/index.html b/blog/2016/08/30/curryon-rome-talk/index.html
index 290bc84b103..5cd3e5d6127 100644
--- a/blog/2016/08/30/curryon-rome-talk/index.html
+++ b/blog/2016/08/30/curryon-rome-talk/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/2016/11/28/atscale16/index.html b/blog/2016/11/28/atscale16/index.html
index bfd76a2bdbc..719ebf8cda6 100644
--- a/blog/2016/11/28/atscale16/index.html
+++ b/blog/2016/11/28/atscale16/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/2017/10/20/ocamlformat-released/index.html b/blog/2017/10/20/ocamlformat-released/index.html
index d8213399d59..694774539b8 100644
--- a/blog/2017/10/20/ocamlformat-released/index.html
+++ b/blog/2017/10/20/ocamlformat-released/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/archive/index.html b/blog/archive/index.html
index 2e0b436c45f..2c64c075306 100644
--- a/blog/archive/index.html
+++ b/blog/archive/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/blog/index.html b/blog/index.html
index 1fbc9cca5d1..a313b3b728a 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/about-Infer/index.html b/docs/1.1.0/about-Infer/index.html
index 28f2a25768f..1585d220944 100644
--- a/docs/1.1.0/about-Infer/index.html
+++ b/docs/1.1.0/about-Infer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/absint-framework/index.html b/docs/1.1.0/absint-framework/index.html
index c75381a2195..d9911b2a050 100644
--- a/docs/1.1.0/absint-framework/index.html
+++ b/docs/1.1.0/absint-framework/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/all-issue-types/index.html b/docs/1.1.0/all-issue-types/index.html
index c560185f0b7..1ea5877a30f 100644
--- a/docs/1.1.0/all-issue-types/index.html
+++ b/docs/1.1.0/all-issue-types/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/analyzing-apps-or-projects/index.html b/docs/1.1.0/analyzing-apps-or-projects/index.html
index 0b451907389..507e7f56911 100644
--- a/docs/1.1.0/analyzing-apps-or-projects/index.html
+++ b/docs/1.1.0/analyzing-apps-or-projects/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-annotation-reachability/index.html b/docs/1.1.0/checker-annotation-reachability/index.html
index 1b364a4cc6e..ec76cf8feb5 100644
--- a/docs/1.1.0/checker-annotation-reachability/index.html
+++ b/docs/1.1.0/checker-annotation-reachability/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-biabduction/index.html b/docs/1.1.0/checker-biabduction/index.html
index c11cfdc064f..a75591ebd34 100644
--- a/docs/1.1.0/checker-biabduction/index.html
+++ b/docs/1.1.0/checker-biabduction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-bufferoverrun/index.html b/docs/1.1.0/checker-bufferoverrun/index.html
index 5899bc4d192..c76b20f979b 100644
--- a/docs/1.1.0/checker-bufferoverrun/index.html
+++ b/docs/1.1.0/checker-bufferoverrun/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-config-checks-between-markers/index.html b/docs/1.1.0/checker-config-checks-between-markers/index.html
index ea7d5824ac7..703a877a5f8 100644
--- a/docs/1.1.0/checker-config-checks-between-markers/index.html
+++ b/docs/1.1.0/checker-config-checks-between-markers/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-config-impact-analysis/index.html b/docs/1.1.0/checker-config-impact-analysis/index.html
index 9e6e6ce0234..1714c7c70d8 100644
--- a/docs/1.1.0/checker-config-impact-analysis/index.html
+++ b/docs/1.1.0/checker-config-impact-analysis/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-cost/index.html b/docs/1.1.0/checker-cost/index.html
index abf87798d42..bb47ae45ed5 100644
--- a/docs/1.1.0/checker-cost/index.html
+++ b/docs/1.1.0/checker-cost/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-dotnet-resource-leak/index.html b/docs/1.1.0/checker-dotnet-resource-leak/index.html
index 6999c6c4a6f..e68703198a5 100644
--- a/docs/1.1.0/checker-dotnet-resource-leak/index.html
+++ b/docs/1.1.0/checker-dotnet-resource-leak/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-eradicate/index.html b/docs/1.1.0/checker-eradicate/index.html
index 9df17611b8a..027b2d62fa6 100644
--- a/docs/1.1.0/checker-eradicate/index.html
+++ b/docs/1.1.0/checker-eradicate/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-fragment-retains-view/index.html b/docs/1.1.0/checker-fragment-retains-view/index.html
index 47599b23c52..de9048902e9 100644
--- a/docs/1.1.0/checker-fragment-retains-view/index.html
+++ b/docs/1.1.0/checker-fragment-retains-view/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-immutable-cast/index.html b/docs/1.1.0/checker-immutable-cast/index.html
index b32597bbb4b..a3cbed896e7 100644
--- a/docs/1.1.0/checker-immutable-cast/index.html
+++ b/docs/1.1.0/checker-immutable-cast/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-impurity/index.html b/docs/1.1.0/checker-impurity/index.html
index 3eecaf5a99b..e3a0f4ad73b 100644
--- a/docs/1.1.0/checker-impurity/index.html
+++ b/docs/1.1.0/checker-impurity/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-inefficient-keyset-iterator/index.html b/docs/1.1.0/checker-inefficient-keyset-iterator/index.html
index c256a0d9137..dc739e595a6 100644
--- a/docs/1.1.0/checker-inefficient-keyset-iterator/index.html
+++ b/docs/1.1.0/checker-inefficient-keyset-iterator/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-linters/index.html b/docs/1.1.0/checker-linters/index.html
index 21824e921e9..225fae6580a 100644
--- a/docs/1.1.0/checker-linters/index.html
+++ b/docs/1.1.0/checker-linters/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-litho-required-props/index.html b/docs/1.1.0/checker-litho-required-props/index.html
index e19fc329a3c..78d8891b648 100644
--- a/docs/1.1.0/checker-litho-required-props/index.html
+++ b/docs/1.1.0/checker-litho-required-props/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-liveness/index.html b/docs/1.1.0/checker-liveness/index.html
index 621c44857d7..de3c21ffab0 100644
--- a/docs/1.1.0/checker-liveness/index.html
+++ b/docs/1.1.0/checker-liveness/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-loop-hoisting/index.html b/docs/1.1.0/checker-loop-hoisting/index.html
index a6a5cca5e10..6c48705fb89 100644
--- a/docs/1.1.0/checker-loop-hoisting/index.html
+++ b/docs/1.1.0/checker-loop-hoisting/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-printf-args/index.html b/docs/1.1.0/checker-printf-args/index.html
index 3a234ff86ed..0152611a9d8 100644
--- a/docs/1.1.0/checker-printf-args/index.html
+++ b/docs/1.1.0/checker-printf-args/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-pulse/index.html b/docs/1.1.0/checker-pulse/index.html
index cc63d61f4e3..46bf4c65bd9 100644
--- a/docs/1.1.0/checker-pulse/index.html
+++ b/docs/1.1.0/checker-pulse/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-purity/index.html b/docs/1.1.0/checker-purity/index.html
index 884403bb232..6f7567e8bdd 100644
--- a/docs/1.1.0/checker-purity/index.html
+++ b/docs/1.1.0/checker-purity/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-quandary/index.html b/docs/1.1.0/checker-quandary/index.html
index fb1cb976e85..bda5ecbae7f 100644
--- a/docs/1.1.0/checker-quandary/index.html
+++ b/docs/1.1.0/checker-quandary/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-racerd/index.html b/docs/1.1.0/checker-racerd/index.html
index b50d9265381..95dd4a61801 100644
--- a/docs/1.1.0/checker-racerd/index.html
+++ b/docs/1.1.0/checker-racerd/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-resource-leak-lab/index.html b/docs/1.1.0/checker-resource-leak-lab/index.html
index df3d93df617..2eceaf57d91 100644
--- a/docs/1.1.0/checker-resource-leak-lab/index.html
+++ b/docs/1.1.0/checker-resource-leak-lab/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-self-in-block/index.html b/docs/1.1.0/checker-self-in-block/index.html
index ba9cab8d112..c7a34391315 100644
--- a/docs/1.1.0/checker-self-in-block/index.html
+++ b/docs/1.1.0/checker-self-in-block/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-siof/index.html b/docs/1.1.0/checker-siof/index.html
index ebbe4285d74..63e23b57b58 100644
--- a/docs/1.1.0/checker-siof/index.html
+++ b/docs/1.1.0/checker-siof/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-starvation/index.html b/docs/1.1.0/checker-starvation/index.html
index ce5491290e8..2e4263de07a 100644
--- a/docs/1.1.0/checker-starvation/index.html
+++ b/docs/1.1.0/checker-starvation/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-topl/index.html b/docs/1.1.0/checker-topl/index.html
index 85bd0e132ff..b44152b4ca1 100644
--- a/docs/1.1.0/checker-topl/index.html
+++ b/docs/1.1.0/checker-topl/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/checker-uninit/index.html b/docs/1.1.0/checker-uninit/index.html
index b9354f59747..800869d2818 100644
--- a/docs/1.1.0/checker-uninit/index.html
+++ b/docs/1.1.0/checker-uninit/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/getting-started/index.html b/docs/1.1.0/getting-started/index.html
index 2460818d0eb..74c589d803b 100644
--- a/docs/1.1.0/getting-started/index.html
+++ b/docs/1.1.0/getting-started/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/hello-world/index.html b/docs/1.1.0/hello-world/index.html
index 3127e46ee75..07beb86fe41 100644
--- a/docs/1.1.0/hello-world/index.html
+++ b/docs/1.1.0/hello-world/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/infer-workflow/index.html b/docs/1.1.0/infer-workflow/index.html
index 3f30db9d883..b4fd80e6872 100644
--- a/docs/1.1.0/infer-workflow/index.html
+++ b/docs/1.1.0/infer-workflow/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/internal-API/index.html b/docs/1.1.0/internal-API/index.html
index a0ea274a67e..d28d336140d 100644
--- a/docs/1.1.0/internal-API/index.html
+++ b/docs/1.1.0/internal-API/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-analyze/index.html b/docs/1.1.0/man-infer-analyze/index.html
index 340be44e5d3..02448ab0351 100644
--- a/docs/1.1.0/man-infer-analyze/index.html
+++ b/docs/1.1.0/man-infer-analyze/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-capture/index.html b/docs/1.1.0/man-infer-capture/index.html
index 076fb67f667..ead1e95c3ed 100644
--- a/docs/1.1.0/man-infer-capture/index.html
+++ b/docs/1.1.0/man-infer-capture/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-compile/index.html b/docs/1.1.0/man-infer-compile/index.html
index b98b0320e6b..73a49338e01 100644
--- a/docs/1.1.0/man-infer-compile/index.html
+++ b/docs/1.1.0/man-infer-compile/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-debug/index.html b/docs/1.1.0/man-infer-debug/index.html
index 16ca2502b17..7bb9f686293 100644
--- a/docs/1.1.0/man-infer-debug/index.html
+++ b/docs/1.1.0/man-infer-debug/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-explore/index.html b/docs/1.1.0/man-infer-explore/index.html
index 13a94283aaa..4a6c787fe74 100644
--- a/docs/1.1.0/man-infer-explore/index.html
+++ b/docs/1.1.0/man-infer-explore/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-help/index.html b/docs/1.1.0/man-infer-help/index.html
index 175ac8c7f4b..9a7a8946b82 100644
--- a/docs/1.1.0/man-infer-help/index.html
+++ b/docs/1.1.0/man-infer-help/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-report/index.html b/docs/1.1.0/man-infer-report/index.html
index 7d3633852e1..1840a6d1c4d 100644
--- a/docs/1.1.0/man-infer-report/index.html
+++ b/docs/1.1.0/man-infer-report/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-reportdiff/index.html b/docs/1.1.0/man-infer-reportdiff/index.html
index 9a78ba3eb23..0ab60520b33 100644
--- a/docs/1.1.0/man-infer-reportdiff/index.html
+++ b/docs/1.1.0/man-infer-reportdiff/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer-run/index.html b/docs/1.1.0/man-infer-run/index.html
index 1d6796ff5fe..1e26b901bdf 100644
--- a/docs/1.1.0/man-infer-run/index.html
+++ b/docs/1.1.0/man-infer-run/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-infer/index.html b/docs/1.1.0/man-infer/index.html
index bebea6d4df5..dc52330ec79 100644
--- a/docs/1.1.0/man-infer/index.html
+++ b/docs/1.1.0/man-infer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/man-pages/index.html b/docs/1.1.0/man-pages/index.html
index 977cbb27cf5..d5c7e5e4058 100644
--- a/docs/1.1.0/man-pages/index.html
+++ b/docs/1.1.0/man-pages/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/separation-logic-and-bi-abduction/index.html b/docs/1.1.0/separation-logic-and-bi-abduction/index.html
index d1a3af0d486..2909a455e85 100644
--- a/docs/1.1.0/separation-logic-and-bi-abduction/index.html
+++ b/docs/1.1.0/separation-logic-and-bi-abduction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/steps-for-ci/index.html b/docs/1.1.0/steps-for-ci/index.html
index 36589c61f7e..d011a00c219 100644
--- a/docs/1.1.0/steps-for-ci/index.html
+++ b/docs/1.1.0/steps-for-ci/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/support/index.html b/docs/1.1.0/support/index.html
index bc869ca2140..b70ed321399 100644
--- a/docs/1.1.0/support/index.html
+++ b/docs/1.1.0/support/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/1.1.0/versions/index.html b/docs/1.1.0/versions/index.html
index f02dcc88ebd..c12f4e4cf55 100644
--- a/docs/1.1.0/versions/index.html
+++ b/docs/1.1.0/versions/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/about-Infer/index.html b/docs/about-Infer/index.html
index 070c91fda66..e7e98fbc299 100644
--- a/docs/about-Infer/index.html
+++ b/docs/about-Infer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/absint-framework/index.html b/docs/absint-framework/index.html
index 5a173939521..59d53e77b55 100644
--- a/docs/absint-framework/index.html
+++ b/docs/absint-framework/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/all-categories/index.html b/docs/all-categories/index.html
index 9d5179c2d89..29c34f10370 100644
--- a/docs/all-categories/index.html
+++ b/docs/all-categories/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/all-checkers/index.html b/docs/all-checkers/index.html
index 3371ad06390..b6cb0040501 100644
--- a/docs/all-checkers/index.html
+++ b/docs/all-checkers/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/all-issue-types/index.html b/docs/all-issue-types/index.html
index 51ae9c46638..1de6cc0ff66 100644
--- a/docs/all-issue-types/index.html
+++ b/docs/all-issue-types/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/analyzing-apps-or-projects/index.html b/docs/analyzing-apps-or-projects/index.html
index cf0a261ef4b..2e428f2ee5d 100644
--- a/docs/analyzing-apps-or-projects/index.html
+++ b/docs/analyzing-apps-or-projects/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-annotation-reachability/index.html b/docs/checker-annotation-reachability/index.html
index 83753f7dbae..ed1e87f6734 100644
--- a/docs/checker-annotation-reachability/index.html
+++ b/docs/checker-annotation-reachability/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-biabduction/index.html b/docs/checker-biabduction/index.html
index b41fac7422d..4f2523a1480 100644
--- a/docs/checker-biabduction/index.html
+++ b/docs/checker-biabduction/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-bufferoverrun/index.html b/docs/checker-bufferoverrun/index.html
index 16e4b9d7db8..63c9676939e 100644
--- a/docs/checker-bufferoverrun/index.html
+++ b/docs/checker-bufferoverrun/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-config-impact-analysis/index.html b/docs/checker-config-impact-analysis/index.html
index 63ecd926003..a1eef3ba778 100644
--- a/docs/checker-config-impact-analysis/index.html
+++ b/docs/checker-config-impact-analysis/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-cost/index.html b/docs/checker-cost/index.html
index 2eac6c2a3e2..8a8d17db7eb 100644
--- a/docs/checker-cost/index.html
+++ b/docs/checker-cost/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-datalog/index.html b/docs/checker-datalog/index.html
index b07deb9785c..18e41c86ab0 100644
--- a/docs/checker-datalog/index.html
+++ b/docs/checker-datalog/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-fragment-retains-view/index.html b/docs/checker-fragment-retains-view/index.html
index b296011b167..51ce657daaa 100644
--- a/docs/checker-fragment-retains-view/index.html
+++ b/docs/checker-fragment-retains-view/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-impurity/index.html b/docs/checker-impurity/index.html
index d14621cade0..d571d43b014 100644
--- a/docs/checker-impurity/index.html
+++ b/docs/checker-impurity/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-inefficient-keyset-iterator/index.html b/docs/checker-inefficient-keyset-iterator/index.html
index 6014a0955b7..41289c39450 100644
--- a/docs/checker-inefficient-keyset-iterator/index.html
+++ b/docs/checker-inefficient-keyset-iterator/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-lineage/index.html b/docs/checker-lineage/index.html
index 4c50a4616d0..d000071da1d 100644
--- a/docs/checker-lineage/index.html
+++ b/docs/checker-lineage/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-litho-required-props/index.html b/docs/checker-litho-required-props/index.html
index 4f3ceca24ef..5d8ac283d54 100644
--- a/docs/checker-litho-required-props/index.html
+++ b/docs/checker-litho-required-props/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-liveness/index.html b/docs/checker-liveness/index.html
index 65db77851ee..6181ff14de3 100644
--- a/docs/checker-liveness/index.html
+++ b/docs/checker-liveness/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-loop-hoisting/index.html b/docs/checker-loop-hoisting/index.html
index 6ea0147539f..99d66ffa8e6 100644
--- a/docs/checker-loop-hoisting/index.html
+++ b/docs/checker-loop-hoisting/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-parameter-not-null-checked/index.html b/docs/checker-parameter-not-null-checked/index.html
index 41e8bab0063..c77e067d4ac 100644
--- a/docs/checker-parameter-not-null-checked/index.html
+++ b/docs/checker-parameter-not-null-checked/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-printf-args/index.html b/docs/checker-printf-args/index.html
index 6b9cef3b4b2..54f4ceef0b8 100644
--- a/docs/checker-printf-args/index.html
+++ b/docs/checker-printf-args/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-pulse/index.html b/docs/checker-pulse/index.html
index d273f70b500..0a795f45233 100644
--- a/docs/checker-pulse/index.html
+++ b/docs/checker-pulse/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-purity/index.html b/docs/checker-purity/index.html
index 73ee722e01e..6c3dea7796f 100644
--- a/docs/checker-purity/index.html
+++ b/docs/checker-purity/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-quandary/index.html b/docs/checker-quandary/index.html
index 54be1afed50..eaa68096829 100644
--- a/docs/checker-quandary/index.html
+++ b/docs/checker-quandary/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-racerd/index.html b/docs/checker-racerd/index.html
index 89ea256eeec..25ff6939ab3 100644
--- a/docs/checker-racerd/index.html
+++ b/docs/checker-racerd/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-resource-leak-lab/index.html b/docs/checker-resource-leak-lab/index.html
index 4fe3668562b..34db05fe93d 100644
--- a/docs/checker-resource-leak-lab/index.html
+++ b/docs/checker-resource-leak-lab/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-scope-leakage/index.html b/docs/checker-scope-leakage/index.html
index 5799021537b..531226824cb 100644
--- a/docs/checker-scope-leakage/index.html
+++ b/docs/checker-scope-leakage/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-self-in-block/index.html b/docs/checker-self-in-block/index.html
index 93ba8a28977..11a75095a02 100644
--- a/docs/checker-self-in-block/index.html
+++ b/docs/checker-self-in-block/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-sil-validation/index.html b/docs/checker-sil-validation/index.html
index af6c5ce10bc..f4a58a1581b 100644
--- a/docs/checker-sil-validation/index.html
+++ b/docs/checker-sil-validation/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-siof/index.html b/docs/checker-siof/index.html
index 2b532955b81..ca804ae3234 100644
--- a/docs/checker-siof/index.html
+++ b/docs/checker-siof/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-starvation/index.html b/docs/checker-starvation/index.html
index d3d2cb3f0dc..4bbb4e59853 100644
--- a/docs/checker-starvation/index.html
+++ b/docs/checker-starvation/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/checker-topl/index.html b/docs/checker-topl/index.html
index 952443b008c..18134b571cf 100644
--- a/docs/checker-topl/index.html
+++ b/docs/checker-topl/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html
index 314b25e44b9..cdbeb1f7bba 100644
--- a/docs/getting-started/index.html
+++ b/docs/getting-started/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/hello-world/index.html b/docs/hello-world/index.html
index 268a9444c81..83aafb4bb52 100644
--- a/docs/hello-world/index.html
+++ b/docs/hello-world/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/infer-workflow/index.html b/docs/infer-workflow/index.html
index 74fde7d7860..7be724fa89c 100644
--- a/docs/infer-workflow/index.html
+++ b/docs/infer-workflow/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/internal-API/index.html b/docs/internal-API/index.html
index edaba19a524..bdd4852e49d 100644
--- a/docs/internal-API/index.html
+++ b/docs/internal-API/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-analyze/index.html b/docs/man-infer-analyze/index.html
index 397943abedd..5908deca6eb 100644
--- a/docs/man-infer-analyze/index.html
+++ b/docs/man-infer-analyze/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-capture/index.html b/docs/man-infer-capture/index.html
index e86665b92c8..9e010969b52 100644
--- a/docs/man-infer-capture/index.html
+++ b/docs/man-infer-capture/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-compile/index.html b/docs/man-infer-compile/index.html
index 9fb4b6875ab..05c1068251a 100644
--- a/docs/man-infer-compile/index.html
+++ b/docs/man-infer-compile/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-debug/index.html b/docs/man-infer-debug/index.html
index 1faab285bcc..0961eb948a9 100644
--- a/docs/man-infer-debug/index.html
+++ b/docs/man-infer-debug/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-explore/index.html b/docs/man-infer-explore/index.html
index 0bb4c17e30e..cfebdcce03f 100644
--- a/docs/man-infer-explore/index.html
+++ b/docs/man-infer-explore/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-help/index.html b/docs/man-infer-help/index.html
index 22991737e3b..d43d74bec72 100644
--- a/docs/man-infer-help/index.html
+++ b/docs/man-infer-help/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-report/index.html b/docs/man-infer-report/index.html
index bf01287cd56..21fd815cbfe 100644
--- a/docs/man-infer-report/index.html
+++ b/docs/man-infer-report/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-reportdiff/index.html b/docs/man-infer-reportdiff/index.html
index ce06af1c361..9bae43c54bb 100644
--- a/docs/man-infer-reportdiff/index.html
+++ b/docs/man-infer-reportdiff/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer-run/index.html b/docs/man-infer-run/index.html
index a0558d73fb3..83eb0c342e8 100644
--- a/docs/man-infer-run/index.html
+++ b/docs/man-infer-run/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-infer/index.html b/docs/man-infer/index.html
index 9a4eaffac94..2066f1dd86b 100644
--- a/docs/man-infer/index.html
+++ b/docs/man-infer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/man-pages/index.html b/docs/man-pages/index.html
index 74ba744b6df..a2268a6ca16 100644
--- a/docs/man-pages/index.html
+++ b/docs/man-pages/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/next/about-Infer/index.html b/docs/next/about-Infer/index.html
index 3eb65a6527b..dc9fbb0e71f 100644
--- a/docs/next/about-Infer/index.html
+++ b/docs/next/about-Infer/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/next/absint-framework/index.html b/docs/next/absint-framework/index.html
index 9474fbe9380..04c6b60a99b 100644
--- a/docs/next/absint-framework/index.html
+++ b/docs/next/absint-framework/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/next/all-categories/index.html b/docs/next/all-categories/index.html
index 1d77da1d4fd..d977024ea49 100644
--- a/docs/next/all-categories/index.html
+++ b/docs/next/all-categories/index.html
@@ -13,7 +13,7 @@
-
+
@@ -82,6 +82,7 @@ Perf regress
CONFIG_IMPACT
INEFFICIENT_KEYSET_ITERATOR
IPC_ON_UI_THREAD
+LOCK_ON_UI_THREAD
PULSE_CONST_REFABLE
PULSE_READONLY_SHARED_PTR_PARAM
PULSE_UNNECESSARY_COPY
@@ -131,6 +132,7 @@ Runtime ex
BAD_MAP_LATENT
BAD_RECORD
BAD_RECORD_LATENT
+INFINITE_RECURSION
MISSING_REQUIRED_PROP
MUTUAL_RECURSION_CYCLE
NIL_INSERTION_INTO_COLLECTION
diff --git a/docs/next/all-checkers/index.html b/docs/next/all-checkers/index.html
index bff36837883..5b006f9ba38 100644
--- a/docs/next/all-checkers/index.html
+++ b/docs/next/all-checkers/index.html
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/next/all-issue-types/index.html b/docs/next/all-issue-types/index.html
index 06d977286bb..45a0b29e510 100644
--- a/docs/next/all-issue-types/index.html
+++ b/docs/next/all-issue-types/index.html
@@ -13,7 +13,7 @@
-
+
@@ -408,6 +408,9 @@ Example 3: T due to calling another T-costed function
Since the analysis is inter-procedural, another example we can have T cost is if at least one of the callees has T cost.
void call_top_cost_FP ( ) { square_root_FP ( 1 ) ; }
+INFINITE_RECURSION
+Category: Runtime exception . Reported as "Infinite Recursion" by pulse .
+A special case of MUTUAL_RECURSION_CYCLE where we detected that the recursive call is made with the exact same values, which guarantees an infinite recursion.
INTEGER_OVERFLOW_L1
Reported as "Integer Overflow L1" by bufferoverrun .
This is reported when integer overflow occurred by integer operations such as addition, subtraction,
@@ -498,6 +501,11 @@
Category: Perf regression . Reported as "Lock on UI Thread" by starvation .
+A method annoted as being on UIThread acquires a lock. This could be a potential performance issue
+Example:
+class Example { @UiThread void foo ( ) { synchronized ( this ) { } } }
MEMORY_LEAK_C
Category: Resource leak . Reported as "Memory Leak" by pulse .
Memory leak in C
@@ -1365,6 +1373,6 @@ Replace weakSelf
with self
:
[ self foo : ^ ( ) { [ self bar ] ; } ] ;
Limitations: To keep this check simple and intra-procedural, we rely on names to find weakSelf
:
-we assume that any captured weak pointer whose name contains "self" is a weak reference to self
.
+we assume that any captured weak pointer whose name contains "self" is a weak reference to self
.