Moving printf args checker into Infer

Summary: public Refactoring Printfargs checker a bit to
make it callable from symbolic executor, then calling it.

Reviewed By: jeremydubreil

Differential Revision: D2361286

fb-gh-sync-id: 4b73855
master
Sam Blackshear 9 years ago committed by facebook-github-bot-7
parent 286d27be10
commit 04f92614e8

@ -281,7 +281,8 @@ def should_report(analyzer, row):
'RETAIN_CYCLE', 'RETAIN_CYCLE',
'ASSERTION_FAILURE', 'ASSERTION_FAILURE',
'ACTIVITY_LEAK', 'ACTIVITY_LEAK',
'BAD_POINTER_COMPARISON' 'BAD_POINTER_COMPARISON',
'CHECKERS_PRINTF_ARGS'
] ]
if analyzer in [ERADICATE, CHECKERS, TRACING]: if analyzer in [ERADICATE, CHECKERS, TRACING]:

@ -826,6 +826,9 @@ let normalize_params pdesc prop actual_params =
let prop, args = IList.fold_left norm_arg (prop, []) actual_params in let prop, args = IList.fold_left norm_arg (prop, []) actual_params in
(prop, IList.rev args) (prop, IList.rev args)
let do_error_checks node instr pname pdesc =
if !Config.curr_language = Config.Java then PrintfArgs.check_printf_args_ok node instr pname pdesc
(** Execute [instr] with a symbolic heap [prop].*) (** Execute [instr] with a symbolic heap [prop].*)
let rec sym_exec cfg tenv pdesc _instr (_prop: Prop.normal Prop.t) path let rec sym_exec cfg tenv pdesc _instr (_prop: Prop.normal Prop.t) path
: (Prop.normal Prop.t * Paths.Path.t) list = : (Prop.normal Prop.t * Paths.Path.t) list =
@ -948,6 +951,7 @@ let rec sym_exec cfg tenv pdesc _instr (_prop: Prop.normal Prop.t) path
sym_exe_builtin cfg pdesc instr tenv _prop path ret_ids args callee_pname loc sym_exe_builtin cfg pdesc instr tenv _prop path ret_ids args callee_pname loc
| Sil.Call (ret_ids, Sil.Const (Sil.Cfun callee_pname), actual_params, loc, call_flags) -> | Sil.Call (ret_ids, Sil.Const (Sil.Cfun callee_pname), actual_params, loc, call_flags) ->
(** Generic fun call with known name *) (** Generic fun call with known name *)
do_error_checks (Paths.Path.curr_node path) instr pname pdesc;
let (prop_r, _n_actual_params) = normalize_params pname _prop actual_params in let (prop_r, _n_actual_params) = normalize_params pname _prop actual_params in
let fn, n_actual_params = handle_special_cases_call tenv cfg callee_pname _n_actual_params in let fn, n_actual_params = handle_special_cases_call tenv cfg callee_pname _n_actual_params in
let resolved_pname = let resolved_pname =

@ -122,13 +122,11 @@ let rec format_string_type_names
let printf_args_name = "CHECKERS_PRINTF_ARGS" let printf_args_name = "CHECKERS_PRINTF_ARGS"
let callback_printf_args let check_printf_args_ok
(all_procs : Procname.t list) (node: Cfg.Node.t)
(get_proc_desc: Procname.t -> Cfg.Procdesc.t option) (instr: Sil.instr)
(idenv: Idenv.t)
(tenv: Sil.tenv)
(proc_name: Procname.t) (proc_name: Procname.t)
(proc_desc : Cfg.Procdesc.t) : unit = (proc_desc: Cfg.Procdesc.t): unit =
(* Check if format string lines up with arguments *) (* Check if format string lines up with arguments *)
let rec check_type_names instr_loc n_arg instr_proc_name fmt_type_names arg_type_names = let rec check_type_names instr_loc n_arg instr_proc_name fmt_type_names arg_type_names =
@ -184,44 +182,49 @@ let callback_printf_args
| Sil.Const c -> PatternMatch.java_get_const_type_name c | Sil.Const c -> PatternMatch.java_get_const_type_name c
| _ -> raise (Failure "Could not resolve fixed type name") in | _ -> raise (Failure "Could not resolve fixed type name") in
let do_instr match instr with
(node: Cfg.Node.t) | Sil.Call (_, Sil.Const (Sil.Cfun pn), args, cl, _) -> (
(instr: Sil.instr): unit = match printf_like_function pn with
match instr with | Some printf -> (
| Sil.Call (_, Sil.Const (Sil.Cfun pn), args, cl, _) -> ( try
match printf_like_function pn with let fmt, fixed_nvars, array_nvar = format_arguments printf args in
| Some printf -> ( let instrs = Cfg.Node.get_instrs node in
try let fixed_nvar_type_names = IList.map (fixed_nvar_type_name instrs) fixed_nvars in
let fmt, fixed_nvars, array_nvar = format_arguments printf args in let vararg_ivar_type_names = match array_nvar with
let instrs = Cfg.Node.get_instrs node in | Some nvar -> (
let fixed_nvar_type_names = IList.map (fixed_nvar_type_name instrs) fixed_nvars in let ivar = array_ivar instrs nvar in
let vararg_ivar_type_names = match array_nvar with PatternMatch.get_vararg_type_names node ivar)
| Some nvar -> ( | None -> [] in
let ivar = array_ivar instrs nvar in match fmt with
PatternMatch.get_vararg_type_names node ivar) | Some fmt ->
| None -> [] in check_type_names
match fmt with cl
| Some fmt -> (printf.format_pos + 1)
check_type_names pn
cl (format_string_type_names fmt 0)
(printf.format_pos + 1) (fixed_nvar_type_names@ vararg_ivar_type_names)
pn | None ->
(format_string_type_names fmt 0) Checkers.ST.report_error
(fixed_nvar_type_names@ vararg_ivar_type_names) proc_name
| None -> proc_desc
Checkers.ST.report_error printf_args_name
proc_name cl
proc_desc "Format string must be string literal"
printf_args_name with e ->
cl L.stderr
"Format string must be string literal" "%s Exception when analyzing %s: %s@."
with e -> printf_args_name
L.stderr (Procname.to_string proc_name)
"%s Exception when analyzing %s: %s@." (Printexc.to_string e))
printf_args_name | None -> ())
(Procname.to_string proc_name) | _ -> ()
(Printexc.to_string e))
| None -> ()) let callback_printf_args
| _ -> () in (all_procs : Procname.t list)
(get_proc_desc: Procname.t -> Cfg.Procdesc.t option)
Cfg.Procdesc.iter_instrs do_instr proc_desc (idenv: Idenv.t)
(tenv: Sil.tenv)
(proc_name: Procname.t)
(proc_desc : Cfg.Procdesc.t) : unit =
Cfg.Procdesc.iter_instrs (fun n i -> check_printf_args_ok n i proc_name proc_desc) proc_desc

@ -17,5 +17,6 @@ type printf_signature = {
val add_printf_like_function : printf_signature -> unit val add_printf_like_function : printf_signature -> unit
val check_printf_args_ok : Cfg.Node.t -> Sil.instr -> Procname.t -> Cfg.Procdesc.t -> unit
val callback_printf_args: Callbacks.proc_callback_t val callback_printf_args: Callbacks.proc_callback_t

Loading…
Cancel
Save