Skip to content

Commit

Permalink
[clang] Limit the depths of secialisations to avoid pathological cases
Browse files Browse the repository at this point in the history
Summary: In unusual cases we can create very large procedures that then take too much memory to process. We should avoid this.

Reviewed By: ngorogiannis

Differential Revision: D50223700

fbshipit-source-id: f2186dc232fee643b08afec7b2d869a6f331e096
  • Loading branch information
dulmarod authored and facebook-github-bot committed Oct 16, 2023
1 parent f1b1b70 commit d6a7bd6
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 16 deletions.
3 changes: 3 additions & 0 deletions infer/man/man1/infer-analyze.txt
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,9 @@ LINEAGE OPTIONS
type is the type of a variable whose value is within a statically
known atom set. The width of the type is the cardinal of that atom
set.

--specialized-proc-depth int
Maximal depth for the specialized procedures created.
PULSE CHECKER OPTIONS
--pulse-cut-to-one-path-procedures-pattern string
Regex of methods for which pulse will only explore one path. Can
Expand Down
4 changes: 4 additions & 0 deletions infer/man/man1/infer-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,10 @@ OPTIONS
Deactivates: print code excerpts around trace elements
(Conversely: --source-preview) See also infer-explore(1).

--specialized-proc-depth int
Maximal depth for the specialized procedures created.
See also infer-analyze(1).

--sqlite-cache-size int
SQLite cache size in pages (if positive) or kB (if negative),
follows formal of corresponding SQLite PRAGMA. See also infer-analyze(1), infer-capture(1), and infer-run(1).
Expand Down
4 changes: 4 additions & 0 deletions infer/man/man1/infer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,10 @@ OPTIONS
Deactivates: print code excerpts around trace elements
(Conversely: --source-preview) See also infer-explore(1).

--specialized-proc-depth int
Maximal depth for the specialized procedures created.
See also infer-analyze(1).

--sqlite-cache-size int
SQLite cache size in pages (if positive) or kB (if negative),
follows formal of corresponding SQLite PRAGMA. See also infer-analyze(1), infer-capture(1), and infer-run(1).
Expand Down
11 changes: 11 additions & 0 deletions infer/src/IR/Procname.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,17 @@ let to_short_unique_name pname =
DB.append_crc_cutoff proc_id


let should_create_specialized_proc proc_name =
let rec should_create_specialized_proc i proc_name =
match proc_name with
| WithFunctionParameters (procname, _, _) ->
should_create_specialized_proc (i + 1) procname
| _ ->
i < Config.specialized_proc_depth
in
should_create_specialized_proc 0 proc_name


let to_filename pname = to_short_unique_name pname |> Escape.escape_filename

module SQLite = SqliteUtils.MarshalledDataNOTForComparison (struct
Expand Down
2 changes: 2 additions & 0 deletions infer/src/IR/Procname.mli
Original file line number Diff line number Diff line change
Expand Up @@ -554,4 +554,6 @@ val is_hack_sinit : t -> bool

val has_hack_classname : t -> bool

val should_create_specialized_proc : t -> bool

module Normalizer : HashNormalizer.S with type t = t
33 changes: 18 additions & 15 deletions infer/src/backend/CCallSpecializedWithClosures.ml
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,24 @@ let replace_with_specialize_methods instr =


let process proc_desc =
(* For each procdesc:
1. If we are a specialized procdesc:
1.1. Copy original procdesc
1.2. Update closures' uses
2. Update calls' closure arguments
3. Update calls with closures as arguments to specialized calls:
3.1. Create procdescs for specialized callees if they don't already exist
4. Update closure calls
*)
(* 1.
1.1. Create a specialized copy of [proc_desc]'s [orig_pdesc] (if it exists).
1.2. Specialize at instruction level: [foo(f)] when [f = closure] replaces every
use of [f] (calls and as argument) with the corresponding [closure] and its
captured variables. *)
ClosureSubstSpecializedMethod.process proc_desc ;
let proc_name = Procdesc.get_proc_name proc_desc in
if not (Procname.should_create_specialized_proc proc_name) then ()
else
(* For each procdesc:
1. If we are a specialized procdesc:
1.1. Copy original procdesc
1.2. Update closures' uses
2. Update calls' closure arguments
3. Update calls with closures as arguments to specialized calls:
3.1. Create procdescs for specialized callees if they don't already exist
4. Update closure calls
*)
(* 1.
1.1. Create a specialized copy of [proc_desc]'s [orig_pdesc] (if it exists).
1.2. Specialize at instruction level: [foo(f)] when [f = closure] replaces every
use of [f] (calls and as argument) with the corresponding [closure] and its
captured variables. *)
ClosureSubstSpecializedMethod.process proc_desc ;
(* 2.
Replace each indirect use of closure (as argument) with a direct use of closure.
e.g.
Expand Down
8 changes: 8 additions & 0 deletions infer/src/base/Config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3013,6 +3013,12 @@ and shrink_analysis_db =
database."


and specialized_proc_depth =
CLOpt.mk_int ~long:"specialized-proc-depth" ~default:2
~in_help:InferCommand.[(Analyze, manual_lineage)]
"Maximal depth for the specialized procedures created."


and lineage_include_builtins =
CLOpt.mk_bool
~deprecated:["-simple-lineage-include-builtins"]
Expand Down Expand Up @@ -4440,6 +4446,8 @@ and show_buckets = !print_buckets

and shrink_analysis_db = !shrink_analysis_db

and specialized_proc_depth = !specialized_proc_depth

and lineage_include_builtins = !lineage_include_builtins

and lineage_field_depth = !lineage_field_depth
Expand Down
2 changes: 2 additions & 0 deletions infer/src/base/Config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,8 @@ val show_buckets : bool

val shrink_analysis_db : bool

val specialized_proc_depth : int

val lineage_include_builtins : bool

val lineage_field_depth : int
Expand Down
6 changes: 5 additions & 1 deletion infer/src/pulse/Pulse.ml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ module PulseTransferFunctions = struct
(if it was) in the end by [reset_need_closure_specialization] *)
let astate = AbductiveDomain.unset_need_closure_specialization astate in
let maybe_call_specialization callee_pname call_exp ((res, _, _) as call_res) =
if (not needed_closure_specialization) && need_closure_specialization res then (
if
(not needed_closure_specialization)
&& need_closure_specialization res
&& Procname.should_create_specialized_proc callee_pname
then (
L.d_printfln "Trying to closure-specialize %a" Exp.pp call_exp ;
match
PulseClosureSpecialization.make_specialized_call_exp analysis_data
Expand Down

0 comments on commit d6a7bd6

Please sign in to comment.