@ -85,27 +85,19 @@ end
module CFG = ProcCfg . OneInstrPerNode ( ProcCfg . Backward ( ProcCfg . Exceptional ) )
module CFG = ProcCfg . OneInstrPerNode ( ProcCfg . Backward ( ProcCfg . Exceptional ) )
module Analyzer = AbstractInterpreter . Make ( CFG ) ( TransferFunctions )
module Analyzer = AbstractInterpreter . Make ( CFG ) ( TransferFunctions )
let checker { Callbacks . tenv ; summary ; proc_desc } : Specs . summary =
(* It's fine to have a dead store on a type that uses the "scope guard" pattern. These types
let cfg = CFG . from_pdesc proc_desc in
are only read in their destructors , and this is expected / ok .
let invariant_map =
( e . g . , https : // github . com / facebook / folly / blob / master / folly / ScopeGuard . h ) . * )
Analyzer . exec_cfg cfg ( ProcData . make_default proc_desc tenv ) ~ initial : Domain . empty ~ debug : true
let matcher_scope_guard =
in
let of_json init = function
(* we don't want to report in harmless cases like int i = 0; if ( ... ) { i = ... } else { i = ... }
| ` List scope_guards ->
that create an intentional dead store as an attempt to imitate default value semantics .
List . fold scope_guards ~ f : ( fun acc json -> Yojson . Basic . Util . to_string json :: acc ) ~ init
use dead stores to a " sentinel " value as a heuristic for ignoring this case * )
let is_sentinel_exp = function
| Exp . Const Cint i ->
IntLit . iszero i | | IntLit . isnull i
| Exp . Const Cfloat 0 . 0 ->
true
| _ ->
| _ ->
false
init
in
in
let matcher_scope_guard =
let default_scope_guards =
QualifiedCppName . Match . of_fuzzy_qual_names
[ (* C++ *)
[ (* C++ *)
" faiss::ScopeDeleter "
" folly::RWSpinLock::ReadHolder "
; " folly::RWSpinLock::ReadHolder "
; " folly::RWSpinLock::WriteHolder "
; " folly::RWSpinLock::WriteHolder "
; " folly::ScopeGuard "
; " folly::ScopeGuard "
; " folly::SharedMutex::ReadHolder "
; " folly::SharedMutex::ReadHolder "
@ -120,9 +112,26 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
; " std::unique_lock " (* Obj-C *)
; " std::unique_lock " (* Obj-C *)
; " CKComponentScope " ]
; " CKComponentScope " ]
in
in
(* It's fine to have a dead store on a type that uses the "scope guard" pattern. These types
of_json default_scope_guards Config . cxx_scope_guards
are only read in their destructors , and this is expected / ok .
| > QualifiedCppName . Match . of_fuzzy_qual_names
( e . g . , https : // github . com / facebook / folly / blob / master / folly / ScopeGuard . h ) . * )
let checker { Callbacks . tenv ; summary ; proc_desc } : Specs . summary =
let cfg = CFG . from_pdesc proc_desc in
let invariant_map =
Analyzer . exec_cfg cfg ( ProcData . make_default proc_desc tenv ) ~ initial : Domain . empty ~ debug : true
in
(* we don't want to report in harmless cases like int i = 0; if ( ... ) { i = ... } else { i = ... }
that create an intentional dead store as an attempt to imitate default value semantics .
use dead stores to a " sentinel " value as a heuristic for ignoring this case * )
let is_sentinel_exp = function
| Exp . Const Cint i ->
IntLit . iszero i | | IntLit . isnull i
| Exp . Const Cfloat 0 . 0 ->
true
| _ ->
false
in
let rec is_scope_guard = function
let rec is_scope_guard = function
| { Typ . desc = Tstruct name } ->
| { Typ . desc = Tstruct name } ->
QualifiedCppName . Match . match_qualifiers matcher_scope_guard ( Typ . Name . qual_name name )
QualifiedCppName . Match . match_qualifiers matcher_scope_guard ( Typ . Name . qual_name name )
@ -169,3 +178,4 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
in
in
List . iter ( CFG . nodes cfg ) ~ f : report_on_node ;
List . iter ( CFG . nodes cfg ) ~ f : report_on_node ;
summary
summary