Skip to content

Commit cef2f0e

Browse files
Kihong Heofacebook-github-bot
authored andcommitted
Inferbo
Summary: This commit is for Inferbo: Infer-based buffer overrun analyzer. Closes facebook#549 Reviewed By: jvillard Differential Revision: D4439297 Pulled By: sblackshear fbshipit-source-id: ddfb5ba
1 parent c5e962e commit cef2f0e

37 files changed

+3225
-20
lines changed

CONTRIBUTORS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Kihong Heo <[email protected]>
2+
Sungkeun Cho <[email protected]>
3+
Kwangkeun Yi <[email protected]>

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ endif
3838

3939
DIRECT_TESTS=
4040
ifeq ($(BUILD_C_ANALYZERS),yes)
41-
DIRECT_TESTS += c_errors c_frontend cpp_checkers cpp_errors cpp_frontend cpp_quandary
41+
DIRECT_TESTS += c_errors c_frontend c_bufferoverrun cpp_checkers cpp_errors cpp_frontend cpp_quandary
4242
endif
4343
ifeq ($(BUILD_JAVA_ANALYZERS),yes)
4444
DIRECT_TESTS += \

infer/src/IR/Localise.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ let analysis_stops = "ANALYSIS_STOPS"
3232
let array_out_of_bounds_l1 = "ARRAY_OUT_OF_BOUNDS_L1"
3333
let array_out_of_bounds_l2 = "ARRAY_OUT_OF_BOUNDS_L2"
3434
let array_out_of_bounds_l3 = "ARRAY_OUT_OF_BOUNDS_L3"
35+
let buffer_overrun = "BUFFER_OVERRUN"
3536
let class_cast_exception = "CLASS_CAST_EXCEPTION"
3637
let comparing_floats_for_equality = "COMPARING_FLOAT_FOR_EQUALITY"
3738
let condition_is_assignment = "CONDITION_IS_ASSIGNMENT"
@@ -718,6 +719,10 @@ let desc_leak hpred_type_opt value_str_opt resource_opt resource_action_opt loc
718719
{ no_desc with descriptions = bucket_str :: xxx_allocated_to @ by_call_to @ is_not_rxxx_after;
719720
tags = !tags }
720721

722+
let desc_buffer_overrun bucket desc =
723+
let err_desc = { no_desc with descriptions = [desc]; } in
724+
error_desc_set_bucket err_desc bucket Config.show_buckets
725+
721726
(** kind of precondition not met *)
722727
type pnm_kind =
723728
| Pnm_bounds

infer/src/IR/Localise.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ val analysis_stops : t
3030
val array_out_of_bounds_l1 : t
3131
val array_out_of_bounds_l2 : t
3232
val array_out_of_bounds_l3 : t
33+
val buffer_overrun : t
3334
val class_cast_exception : t
3435
val comparing_floats_for_equality : t
3536
val condition_is_assignment : t
@@ -214,6 +215,8 @@ val desc_leak :
214215
Exp.t option -> string option -> PredSymb.resource option -> PredSymb.res_action option ->
215216
Location.t -> string option -> error_desc
216217

218+
val desc_buffer_overrun : string -> string -> error_desc
219+
217220
val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc
218221

219222
val java_unchecked_exn_desc : Procname.t -> Typename.t -> string -> error_desc

infer/src/IR/Procdesc.re

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@ type t = {
294294
mutable nodes: list Node.t, /** list of nodes of this procedure */
295295
mutable nodes_num: int, /** number of nodes */
296296
mutable start_node: Node.t, /** start node of this procedure */
297-
mutable exit_node: Node.t /** exit node of ths procedure */
297+
mutable exit_node: Node.t, /** exit node of ths procedure */
298+
mutable loop_heads: option NodeSet.t /** loop head nodes of this procedure */
298299
}
299300
[@@deriving compare];
300301

@@ -307,7 +308,7 @@ let from_proc_attributes called_from_cfg::called_from_cfg attributes => {
307308
let pname_opt = Some attributes.ProcAttributes.proc_name;
308309
let start_node = Node.dummy pname_opt;
309310
let exit_node = Node.dummy pname_opt;
310-
{attributes, nodes: [], nodes_num: 0, start_node, exit_node}
311+
{attributes, nodes: [], nodes_num: 0, start_node, exit_node, loop_heads: None}
311312
};
312313

313314

@@ -518,3 +519,41 @@ let node_set_succs_exn pdesc (node: Node.t) succs exn =>
518519
set_succs_exn_base node' [exit_node] exn
519520
| _ => set_succs_exn_base node succs exn
520521
};
522+
523+
524+
/** Get loop heads for widening.
525+
It collects all target nodes of back-edges in a depth-first
526+
traversal.
527+
*/
528+
let get_loop_heads pdesc => {
529+
let rec set_loop_head_rec visited heads wl =>
530+
switch wl {
531+
| [] => heads
532+
| [(n, ancester), ...wl'] =>
533+
if (NodeSet.mem n visited) {
534+
if (NodeSet.mem n ancester) {
535+
set_loop_head_rec visited (NodeSet.add n heads) wl'
536+
} else {
537+
set_loop_head_rec visited heads wl'
538+
}
539+
} else {
540+
let ancester = NodeSet.add n ancester;
541+
let succs = IList.append (Node.get_succs n) (Node.get_exn n);
542+
let works = IList.map (fun m => (m, ancester)) succs;
543+
set_loop_head_rec (NodeSet.add n visited) heads (IList.append works wl')
544+
}
545+
};
546+
let start_wl = [(get_start_node pdesc, NodeSet.empty)];
547+
let lh = set_loop_head_rec NodeSet.empty NodeSet.empty start_wl;
548+
pdesc.loop_heads = Some lh;
549+
lh
550+
};
551+
552+
let is_loop_head pdesc (node: Node.t) => {
553+
let lh =
554+
switch pdesc.loop_heads {
555+
| Some lh => lh
556+
| None => get_loop_heads pdesc
557+
};
558+
NodeSet.mem node lh
559+
};

infer/src/IR/Procdesc.rei

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ let fold_calls: ('a => (Procname.t, Location.t) => 'a) => 'a => t => 'a;
166166
let fold_instrs: ('a => Node.t => Sil.instr => 'a) => 'a => t => 'a;
167167

168168

169+
/** fold over all nodes */
170+
let fold_nodes: ('a => Node.t => 'a) => 'a => t => 'a;
171+
172+
169173
/** Only call from Cfg. */
170174
let from_proc_attributes: called_from_cfg::bool => ProcAttributes.t => t;
171175

@@ -274,3 +278,5 @@ let set_start_node: t => Node.t => unit;
274278

275279
/** indicate that we have performed preanalysis on the CFG assoociated with [t] */
276280
let signal_did_preanalysis: t => unit;
281+
282+
let is_loop_head: t => Node.t => bool;

infer/src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ else
121121
EXTRA_DEPS = opensource
122122
endif
123123

124-
DEPENDENCIES = IR backend base checkers eradicate harness integration tp/fts quandary $(EXTRA_DEPS)
124+
DEPENDENCIES = IR backend base checkers eradicate harness integration tp/fts quandary bufferoverrun $(EXTRA_DEPS)
125125

126126
# ocamlbuild command with options common to all build targets
127127
OCAMLBUILD_BASE = rebuild $(OCAMLBUILD_OPTIONS) -j $(NCPU) $(addprefix -I , $(DEPENDENCIES))

infer/src/backend/InferPrint.re

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ let should_report (issue_kind: Exceptions.err_kind) issue_type error_desc eclass
316316
| Checkers
317317
| Eradicate
318318
| Tracing => true
319+
| Bufferoverrun
319320
| Capture
320321
| Compile
321322
| Crashcontext
@@ -347,7 +348,8 @@ let should_report (issue_kind: Exceptions.err_kind) issue_type error_desc eclass
347348
];
348349
IList.mem Localise.equal issue_type null_deref_issue_types
349350
};
350-
if issue_type_is_null_deref {
351+
let issue_type_is_buffer_overrun = Localise.equal issue_type Localise.buffer_overrun;
352+
if (issue_type_is_null_deref || issue_type_is_buffer_overrun) {
351353
let issue_bucket_is_high = {
352354
let issue_bucket = Localise.error_desc_get_bucket error_desc;
353355
let high_buckets = Localise.BucketLevel.[b1, b2];

infer/src/backend/infer.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ let analyze driver_mode =
319319
false, false
320320
| _, (Capture | Compile) ->
321321
false, false
322-
| _, (Infer | Eradicate | Checkers | Tracing | Crashcontext | Quandary | Threadsafety) ->
322+
| _, (Infer | Eradicate | Checkers | Tracing | Crashcontext | Quandary | Threadsafety | Bufferoverrun) ->
323323
true, true
324324
| _, Linters ->
325325
false, true in

infer/src/backend/specs.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ type payload =
327327
quandary : QuandarySummary.t option;
328328
siof : SiofDomain.astate option;
329329
threadsafety : ThreadSafetyDomain.summary option;
330+
buffer_overrun : BufferOverrunDomain.Summary.t option;
330331
}
331332

332333
type summary =
@@ -455,17 +456,18 @@ let pp_summary_no_stats_specs fmt summary =
455456
F.fprintf fmt "%a@\n" pp_pair (describe_phase summary);
456457
F.fprintf fmt "Dependency_map: @[%a@]@\n" pp_dependency_map summary.dependency_map
457458

458-
let pp_payload pe fmt { preposts; typestate; crashcontext_frame; quandary; siof; threadsafety } =
459+
let pp_payload pe fmt { preposts; typestate; crashcontext_frame; quandary; siof; threadsafety; buffer_overrun } =
459460
let pp_opt pp fmt = function
460461
| Some x -> pp fmt x
461462
| None -> () in
462-
F.fprintf fmt "%a%a%a%a%a%a@\n"
463+
F.fprintf fmt "%a%a%a%a%a%a%a@\n"
463464
(pp_specs pe) (get_specs_from_preposts preposts)
464465
(pp_opt (TypeState.pp TypeState.unit_ext)) typestate
465466
(pp_opt Crashcontext.pp_stacktree) crashcontext_frame
466467
(pp_opt QuandarySummary.pp) quandary
467468
(pp_opt SiofDomain.pp) siof
468469
(pp_opt ThreadSafetyDomain.pp_summary) threadsafety
470+
(pp_opt BufferOverrunDomain.Summary.pp) buffer_overrun
469471

470472

471473
let pp_summary_text ~whole_seconds fmt summary =
@@ -753,6 +755,7 @@ let empty_payload =
753755
quandary = None;
754756
siof = None;
755757
threadsafety = None;
758+
buffer_overrun = None;
756759
}
757760

758761
(** [init_summary (depend_list, nodes,

0 commit comments

Comments
 (0)