Skip to content

Commit

Permalink
[dispatch-once-static-init] Make the checker interprocedural
Browse files Browse the repository at this point in the history
Summary: Made the domain into a summary and added necessary scaffolding to make the checker inter-procedural. We still need to improve the location of the report and add traces, will do in a follow up diff.

Reviewed By: skcho

Differential Revision:
D66456757

Privacy Context Container: L1208441

fbshipit-source-id: 1c695ba11a91d0da2e7147d777b15b04169c1201
  • Loading branch information
dulmarod authored and facebook-github-bot committed Nov 26, 2024
1 parent eee6a2c commit 4b3dd96
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 21 deletions.
9 changes: 7 additions & 2 deletions infer/src/backend/Payloads.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type t =
; config_impact_analysis: ConfigImpactAnalysis.Summary.t Lazy.t option
; cost: CostDomain.summary Lazy.t option
; disjunctive_demo: DisjunctiveDemo.domain Lazy.t option
; dispatch_once_static_init: DispatchOnceStaticInit.Summary.t Lazy.t option
; lab_resource_leaks: ResourceLeakDomain.summary Lazy.t option
; litho_required_props: LithoDomain.summary Lazy.t option
; pulse: PulseSummary.t Lazy.t option
Expand Down Expand Up @@ -64,6 +65,7 @@ let all_fields =
~config_impact_analysis:(fun f -> mk f ConfigImpactAnalysis ConfigImpactAnalysis.Summary.pp)
~cost:(fun f -> mk f Cost CostDomain.pp_summary)
~disjunctive_demo:(fun f -> mk f DisjunctiveDemo DisjunctiveDemo.pp_domain)
~dispatch_once_static_init:(fun f -> mk f DisjunctiveDemo DispatchOnceStaticInit.Summary.pp)
~litho_required_props:(fun f -> mk f LithoRequiredProps LithoDomain.pp_summary)
~pulse:(fun f -> mk_full f Pulse PulseSummary.pp)
~purity:(fun f -> mk f Purity PurityDomain.pp_summary)
Expand Down Expand Up @@ -108,6 +110,7 @@ let empty =
; config_impact_analysis= None
; cost= None
; disjunctive_demo= None
; dispatch_once_static_init= None
; lab_resource_leaks= None
; litho_required_props= None
; pulse= None
Expand Down Expand Up @@ -206,8 +209,9 @@ module SQLite = struct
Fields.make_creator ~annot_map:data_of_sqlite_column ~biabduction:data_of_sqlite_column
~buffer_overrun_analysis:data_of_sqlite_column ~buffer_overrun_checker:data_of_sqlite_column
~config_impact_analysis:data_of_sqlite_column ~cost:data_of_sqlite_column
~disjunctive_demo:data_of_sqlite_column ~litho_required_props:data_of_sqlite_column
~pulse:data_of_sqlite_column ~purity:data_of_sqlite_column ~racerd:data_of_sqlite_column
~disjunctive_demo:data_of_sqlite_column ~dispatch_once_static_init:data_of_sqlite_column
~litho_required_props:data_of_sqlite_column ~pulse:data_of_sqlite_column
~purity:data_of_sqlite_column ~racerd:data_of_sqlite_column
~lab_resource_leaks:data_of_sqlite_column ~scope_leakage:data_of_sqlite_column
~siof:data_of_sqlite_column ~lineage:data_of_sqlite_column
~lineage_shape:data_of_sqlite_column ~starvation:data_of_sqlite_column
Expand Down Expand Up @@ -257,6 +261,7 @@ module SQLite = struct
; config_impact_analysis= load table ~proc_uid ConfigImpactAnalysis
; cost= load table ~proc_uid Cost
; disjunctive_demo= load table ~proc_uid DisjunctiveDemo
; dispatch_once_static_init= load table ~proc_uid DispatchOnceStaticInit
; lab_resource_leaks= load table ~proc_uid LabResourceLeaks
; litho_required_props= load table ~proc_uid LithoRequiredProps
; pulse= load table ~proc_uid Pulse
Expand Down
1 change: 1 addition & 0 deletions infer/src/backend/Payloads.mli
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ include sig
; config_impact_analysis: ConfigImpactAnalysis.Summary.t Lazy.t option
; cost: CostDomain.summary Lazy.t option
; disjunctive_demo: DisjunctiveDemo.domain Lazy.t option
; dispatch_once_static_init: DispatchOnceStaticInit.Summary.t Lazy.t option
; lab_resource_leaks: ResourceLeakDomain.summary Lazy.t option
; litho_required_props: LithoDomain.summary Lazy.t option
; pulse: PulseSummary.t Lazy.t option
Expand Down
4 changes: 3 additions & 1 deletion infer/src/backend/registerCheckers.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ let all_checkers =
; { checker= ParameterNotNullChecked
; callbacks= [(intraprocedural ParameterNotNullChecked.checker, Clang)] }
; { checker= DispatchOnceStaticInit
; callbacks= [(intraprocedural DispatchOnceStaticInit.checker, Clang)] }
; callbacks=
[ ( interprocedural Payloads.Fields.dispatch_once_static_init DispatchOnceStaticInit.checker
, Clang ) ] }
; { checker= BufferOverrunAnalysis
; callbacks=
(let bo_analysis =
Expand Down
3 changes: 3 additions & 0 deletions infer/src/base/PayloadId.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type t =
| ConfigImpactAnalysis
| Cost
| DisjunctiveDemo
| DispatchOnceStaticInit
| LabResourceLeaks
| LithoRequiredProps
| Pulse
Expand Down Expand Up @@ -45,6 +46,8 @@ let to_checker payload_id : Checker.t =
Cost
| DisjunctiveDemo ->
DisjunctiveDemo
| DispatchOnceStaticInit ->
DispatchOnceStaticInit
| LabResourceLeaks ->
ResourceLeakLabExercise
| LithoRequiredProps ->
Expand Down
1 change: 1 addition & 0 deletions infer/src/base/PayloadId.mli
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type t =
| ConfigImpactAnalysis
| Cost
| DisjunctiveDemo
| DispatchOnceStaticInit
| LabResourceLeaks
| LithoRequiredProps
| Pulse
Expand Down
42 changes: 26 additions & 16 deletions infer/src/checkers/DispatchOnceStaticInit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,33 @@ module Mem = struct
let pp fmt {loc} = F.fprintf fmt "calls_dispatch_once at %a" Location.pp loc
end

module Domain = struct
module Summary = struct
include AbstractDomain.FiniteSet (Mem)

let add_calls_dispatch_once loc astate = add {Mem.loc} astate
end

module TransferFunctions = struct
module Domain = Domain
module Domain = Summary
module CFG = ProcCfg.Normal

type analysis_data = IntraproceduralAnalysis.t
type analysis_data = Summary.t InterproceduralAnalysis.t

let pp_session_name _node fmt = F.pp_print_string fmt "DispatchOnceStaticInit"

let exec_instr (astate : Domain.t) _ _cfg_node _ (instr : Sil.instr) =
let exec_instr (astate : Summary.t) {InterproceduralAnalysis.analyze_dependency} _cfg_node _
(instr : Sil.instr) =
match instr with
| Call (_, Exp.Const (Const.Cfun procname), _, loc, _) ->
let astate =
match analyze_dependency procname with
| Ok summary ->
Summary.join astate summary
| Error _ ->
astate
in
let calls_dispatch_once = String.equal "_dispatch_once" (Procname.get_method procname) in
if calls_dispatch_once then Domain.add_calls_dispatch_once loc astate else astate
if calls_dispatch_once then Summary.add_calls_dispatch_once loc astate else astate
| _ ->
astate
end
Expand All @@ -55,16 +63,18 @@ let report_issue proc_desc err_log {Mem.loc} =
IssueType.dispatch_once_in_static_init message


let checker ({IntraproceduralAnalysis.proc_desc; err_log} as analysis_data) =
let checker ({InterproceduralAnalysis.proc_desc; err_log} as analysis_data) =
let attributes = Procdesc.get_attributes proc_desc in
if attributes.ProcAttributes.is_static_ctor then
let initial = Domain.empty in
match Analyzer.compute_post analysis_data ~initial proc_desc with
| Some domain -> (
match Domain.choose_opt domain with
| Some mem ->
report_issue proc_desc err_log mem
let initial = Summary.empty in
let summary_opt = Analyzer.compute_post analysis_data ~initial proc_desc in
( if attributes.ProcAttributes.is_static_ctor then
match summary_opt with
| Some domain -> (
match Summary.choose_opt domain with
| Some mem ->
report_issue proc_desc err_log mem
| None ->
() )
| None ->
() )
| None ->
()
() ) ;
summary_opt
20 changes: 20 additions & 0 deletions infer/src/checkers/DispatchOnceStaticInit.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format

module Mem : sig
type t = {loc: Location.t}

val compare : t -> t -> int

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

module Summary : module type of AbstractDomain.FiniteSet (Mem)

val checker : Summary.t InterproceduralAnalysis.t -> Summary.t option
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ + (instancetype)getInstance {

@end

__attribute__((constructor)) static void initializer_test_interproc_bad_FN(
void) {
__attribute__((constructor)) static void initializer_test_interproc_bad(void) {
[Manager getInstance];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
codetoanalyze/objc/dispatch-once-static-init/DispatchOnceInStaticInit.m, initializer_test_interproc_bad, -8, DISPATCH_ONCE_IN_STATIC_INIT, no_bucket, ERROR, [macro expanded here,Call to `dispatch_once` here]
codetoanalyze/objc/dispatch-once-static-init/DispatchOnceInStaticInit.m, initializer_test_intraproc_bad, 3, DISPATCH_ONCE_IN_STATIC_INIT, no_bucket, ERROR, [macro expanded here,Call to `dispatch_once` here]

0 comments on commit 4b3dd96

Please sign in to comment.