|
|
|
@ -152,80 +152,98 @@ struct
|
|
|
|
|
~inst_num ~dimension:(dimension + 1) mem
|
|
|
|
|
| _ -> mem
|
|
|
|
|
|
|
|
|
|
let declare_symbolic_array
|
|
|
|
|
let counter_gen init =
|
|
|
|
|
let num_ref = ref init in
|
|
|
|
|
let get_num () =
|
|
|
|
|
let v = !num_ref in
|
|
|
|
|
num_ref := v + 1;
|
|
|
|
|
v
|
|
|
|
|
in
|
|
|
|
|
get_num
|
|
|
|
|
|
|
|
|
|
let declare_symbolic_val
|
|
|
|
|
: Typ.Procname.t -> Tenv.t -> CFG.node -> Loc.t -> Typ.t -> inst_num:int
|
|
|
|
|
-> sym_num:int -> dimension:int -> Dom.Mem.astate -> Dom.Mem.astate * int
|
|
|
|
|
= fun pname tenv node loc typ ~inst_num ~sym_num ~dimension mem ->
|
|
|
|
|
let offset = Itv.make_sym pname sym_num in
|
|
|
|
|
let size = Itv.make_sym pname (sym_num + 2) in
|
|
|
|
|
let arr =
|
|
|
|
|
Sem.eval_array_alloc pname node typ offset size inst_num dimension
|
|
|
|
|
in
|
|
|
|
|
let elem_val = Dom.Val.make_sym pname (sym_num + 4) in
|
|
|
|
|
let arr_loc = arr |> Dom.Val.get_array_blk |> ArrayBlk.get_pow_loc in
|
|
|
|
|
let mem =
|
|
|
|
|
mem
|
|
|
|
|
|> Dom.Mem.add_heap loc arr
|
|
|
|
|
|> Dom.Mem.strong_update_heap arr_loc elem_val
|
|
|
|
|
in
|
|
|
|
|
let decl_fld (mem, sym_num) (fn, typ, _) =
|
|
|
|
|
let loc =
|
|
|
|
|
mem |> Dom.Mem.find_heap loc |> Dom.Val.get_array_locs |> PowLoc.choose
|
|
|
|
|
-> new_sym_num: (unit -> int) -> Domain.t -> Domain.t
|
|
|
|
|
= fun pname tenv node loc typ ~inst_num ~new_sym_num mem ->
|
|
|
|
|
let max_depth = 2 in
|
|
|
|
|
let new_alloc_num = counter_gen 1 in
|
|
|
|
|
let rec decl_sym_fld ~depth loc typ mem =
|
|
|
|
|
if depth > max_depth then mem else
|
|
|
|
|
let depth = depth + 1 in
|
|
|
|
|
match typ.Typ.desc with
|
|
|
|
|
| Typ.Tint ikind ->
|
|
|
|
|
let unsigned = Typ.ikind_is_unsigned ikind in
|
|
|
|
|
let sym_num = new_sym_num () in
|
|
|
|
|
let _ = new_sym_num () in
|
|
|
|
|
let v = Dom.Val.make_sym ~unsigned pname sym_num in
|
|
|
|
|
Dom.Mem.add_heap loc v mem
|
|
|
|
|
| Typ.Tfloat _ ->
|
|
|
|
|
let sym_num = new_sym_num () in
|
|
|
|
|
let _ = new_sym_num () in
|
|
|
|
|
let v = Dom.Val.make_sym pname sym_num in
|
|
|
|
|
Dom.Mem.add_heap loc v mem
|
|
|
|
|
| Typ.Tptr (typ, _) ->
|
|
|
|
|
decl_sym_arr ~depth loc typ mem
|
|
|
|
|
| Typ.Tarray (typ, opt_int_lit, _) ->
|
|
|
|
|
let opt_size = Option.map ~f:Itv.of_int_lit opt_int_lit in
|
|
|
|
|
let opt_offset = Some Itv.zero in
|
|
|
|
|
decl_sym_arr ~depth loc typ ~opt_offset ~opt_size mem
|
|
|
|
|
| Typ.Tstruct typename ->
|
|
|
|
|
let decl_fld mem (fn, typ, _) =
|
|
|
|
|
let loc_fld = Loc.append_field loc fn in
|
|
|
|
|
decl_sym_fld ~depth loc_fld typ mem
|
|
|
|
|
in
|
|
|
|
|
let decl_flds str =
|
|
|
|
|
List.fold ~f:decl_fld ~init:mem str.Typ.Struct.fields
|
|
|
|
|
in
|
|
|
|
|
let opt_struct = Tenv.lookup tenv typename in
|
|
|
|
|
Option.value_map opt_struct ~default:mem ~f:decl_flds
|
|
|
|
|
| _ ->
|
|
|
|
|
if Config.bo_debug >= 3 then
|
|
|
|
|
L.(debug BufferOverrun Verbose) "/!\\ decl_fld of unhandled type: %a at %a@."
|
|
|
|
|
(Typ.pp Pp.text) typ
|
|
|
|
|
Location.pp (CFG.loc node);
|
|
|
|
|
mem
|
|
|
|
|
|
|
|
|
|
and decl_sym_arr ~depth loc typ ?(opt_offset=None) ?(opt_size=None) mem =
|
|
|
|
|
let option_value opt_x default_f =
|
|
|
|
|
match opt_x with
|
|
|
|
|
| Some x -> x
|
|
|
|
|
| None -> default_f ()
|
|
|
|
|
in
|
|
|
|
|
let field = Loc.append_field loc fn in
|
|
|
|
|
match typ.Typ.desc with
|
|
|
|
|
| Typ.Tint ikind ->
|
|
|
|
|
let unsigned = Typ.ikind_is_unsigned ikind in
|
|
|
|
|
let v = Dom.Val.make_sym ~unsigned pname sym_num in
|
|
|
|
|
(Dom.Mem.add_heap field v mem, sym_num + 2)
|
|
|
|
|
| Typ.Tfloat _ ->
|
|
|
|
|
let v = Dom.Val.make_sym pname sym_num in
|
|
|
|
|
(Dom.Mem.add_heap field v mem, sym_num + 2)
|
|
|
|
|
| Typ.Tptr (typ, _) ->
|
|
|
|
|
let offset = Itv.make_sym pname sym_num in
|
|
|
|
|
let size = Itv.make_sym pname (sym_num + 2) in
|
|
|
|
|
let v =
|
|
|
|
|
Sem.eval_array_alloc pname node typ offset size inst_num dimension
|
|
|
|
|
in
|
|
|
|
|
(Dom.Mem.add_heap field v mem, sym_num + 4)
|
|
|
|
|
| _ ->
|
|
|
|
|
L.(debug BufferOverrun Verbose) "/!\\ decl_fld of unhandled type: %a at %a@."
|
|
|
|
|
(Typ.pp Pp.text) typ
|
|
|
|
|
Location.pp (CFG.loc node);
|
|
|
|
|
(mem, sym_num)
|
|
|
|
|
let itv_make_sym () =
|
|
|
|
|
let sym_num = new_sym_num () in
|
|
|
|
|
let _ = new_sym_num () in
|
|
|
|
|
Itv.make_sym pname sym_num
|
|
|
|
|
in
|
|
|
|
|
let offset = option_value opt_offset itv_make_sym in
|
|
|
|
|
let size = option_value opt_size itv_make_sym in
|
|
|
|
|
let alloc_num = new_alloc_num () in
|
|
|
|
|
let arr =
|
|
|
|
|
Sem.eval_array_alloc pname node typ offset size inst_num alloc_num
|
|
|
|
|
in
|
|
|
|
|
let mem = Dom.Mem.add_heap loc arr mem in
|
|
|
|
|
let deref_loc =
|
|
|
|
|
Loc.of_allocsite (Sem.get_allocsite pname node inst_num alloc_num)
|
|
|
|
|
in
|
|
|
|
|
decl_sym_fld ~depth deref_loc typ mem
|
|
|
|
|
in
|
|
|
|
|
match typ.Typ.desc with
|
|
|
|
|
| Typ.Tstruct typename ->
|
|
|
|
|
(match Tenv.lookup tenv typename with
|
|
|
|
|
| Some str ->
|
|
|
|
|
List.fold ~f:decl_fld ~init:(mem, sym_num + 6) str.Typ.Struct.fields
|
|
|
|
|
| _ -> (mem, sym_num + 6))
|
|
|
|
|
| _ -> (mem, sym_num + 6)
|
|
|
|
|
decl_sym_fld ~depth:0 loc typ mem
|
|
|
|
|
|
|
|
|
|
let declare_symbolic_parameter
|
|
|
|
|
: Procdesc.t -> Tenv.t -> CFG.node -> int -> Dom.Mem.astate -> Dom.Mem.astate
|
|
|
|
|
= fun pdesc tenv node inst_num mem ->
|
|
|
|
|
let pname = Procdesc.get_proc_name pdesc in
|
|
|
|
|
let add_formal (mem, inst_num, sym_num) (pvar, typ) =
|
|
|
|
|
match typ.Typ.desc with
|
|
|
|
|
| Typ.Tint ikind ->
|
|
|
|
|
let unsigned = Typ.ikind_is_unsigned ikind in
|
|
|
|
|
let v = Dom.Val.make_sym ~unsigned pname sym_num in
|
|
|
|
|
let mem = Dom.Mem.add_heap (Loc.of_pvar pvar) v mem in
|
|
|
|
|
(mem, inst_num + 1, sym_num + 2)
|
|
|
|
|
| Typ.Tptr (typ, _) ->
|
|
|
|
|
let (mem, sym_num) =
|
|
|
|
|
declare_symbolic_array pname tenv node (Loc.of_pvar pvar) typ
|
|
|
|
|
~inst_num ~sym_num ~dimension:1 mem
|
|
|
|
|
in
|
|
|
|
|
(mem, inst_num + 1, sym_num)
|
|
|
|
|
| _ ->
|
|
|
|
|
L.(debug BufferOverrun Verbose) "declare_symbolic_parameter of unhandled type: %a@."
|
|
|
|
|
(Typ.pp Pp.text) typ;
|
|
|
|
|
(mem, inst_num, sym_num) (* TODO: add other cases if necessary *)
|
|
|
|
|
let new_sym_num = counter_gen 0 in
|
|
|
|
|
let add_formal (mem, inst_num) (pvar, typ) =
|
|
|
|
|
let loc = Loc.of_pvar pvar in
|
|
|
|
|
let mem =
|
|
|
|
|
declare_symbolic_val pname tenv node loc typ ~inst_num ~new_sym_num mem
|
|
|
|
|
in
|
|
|
|
|
(mem, inst_num + 1)
|
|
|
|
|
in
|
|
|
|
|
List.fold ~f:add_formal ~init:(mem, inst_num, 0) (Sem.get_formals pdesc)
|
|
|
|
|
|> fst3
|
|
|
|
|
List.fold ~f:add_formal ~init:(mem, inst_num) (Sem.get_formals pdesc)
|
|
|
|
|
|> fst
|
|
|
|
|
|
|
|
|
|
let instantiate_ret ret callee_pname callee_exit_mem subst_map mem =
|
|
|
|
|
match ret with
|
|
|
|
@ -365,15 +383,17 @@ struct
|
|
|
|
|
| Exp.Var _ ->
|
|
|
|
|
let arr = Sem.eval exp mem loc |> Dom.Val.get_array_blk in
|
|
|
|
|
Some (arr, Itv.zero, true)
|
|
|
|
|
| Exp.Lindex (e1, e2)
|
|
|
|
|
| Exp.BinOp (Binop.PlusA, e1, e2) ->
|
|
|
|
|
let arr = Sem.eval e1 mem loc |> Dom.Val.get_array_blk in
|
|
|
|
|
| Exp.Lindex (e1, e2) ->
|
|
|
|
|
let locs = Sem.eval_locs e1 mem loc |> Dom.Val.get_all_locs in
|
|
|
|
|
let arr = Dom.Mem.find_set locs mem |> Dom.Val.get_array_blk in
|
|
|
|
|
let idx = Sem.eval e2 mem loc |> Dom.Val.get_itv in
|
|
|
|
|
Some (arr, idx, true)
|
|
|
|
|
| Exp.BinOp (Binop.MinusA, e1, e2) ->
|
|
|
|
|
| Exp.BinOp (Binop.PlusA as bop, e1, e2)
|
|
|
|
|
| Exp.BinOp (Binop.MinusA as bop, e1, e2) ->
|
|
|
|
|
let arr = Sem.eval e1 mem loc |> Dom.Val.get_array_blk in
|
|
|
|
|
let idx = Sem.eval e2 mem loc |> Dom.Val.get_itv in
|
|
|
|
|
Some (arr, idx, false)
|
|
|
|
|
let is_plus = Binop.equal bop Binop.PlusA in
|
|
|
|
|
Some (arr, idx, is_plus)
|
|
|
|
|
| _ -> None
|
|
|
|
|
in
|
|
|
|
|
match array_access with
|
|
|
|
|