Skip to content

Commit

Permalink
[doEdit] declear tmp variables if does not exist in donee
Browse files Browse the repository at this point in the history
  • Loading branch information
spearo2 committed Jul 22, 2024
1 parent 77ca1ec commit a8efab1
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/absDiff.ml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ and abs_stmt =
and abs_global = SGNull | SGFun | GVar of string * string
and abs_node = { ast : abs_ast; ids : StrSet.t; literal : string }

let get_ids node = node.ids

let get_original_exp node =
match node.ast with
| AbsExp (_, e) -> e
Expand Down
7 changes: 7 additions & 0 deletions src/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ let s_location (loc : Cil.location) =
get_loc_filename loc ^ ":" ^ string_of_int loc.line

let tostring s = Escape.escape_string (Pretty.sprint ~width:0 s)
let s_attrs attrs = tostring (d_attrlist () attrs)
let s_attr attr = tostring (d_attr () attr)

let s_glob g =
match g with
Expand Down Expand Up @@ -138,6 +140,11 @@ and s_offset = function
and s_uop u = tostring (d_unop () u)
and s_bop b = tostring (d_binop () b)

and s_varinfo vi =
let name = vi.vname in
let typ = s_type vi.vtype in
name ^ ":" ^ typ

and s_instr i =
match i with
| Set (lv, exp, _) -> "Set(" ^ s_lv lv ^ "," ^ s_exp exp ^ ")"
Expand Down
136 changes: 134 additions & 2 deletions src/doEdit.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,124 @@ module EF = EditFunction
module H = Utils
module L = Logger

let target_func = ref []
let patron_tmp_var_cnt = ref 0
let vdec_map = Hashtbl.create (module String)

class funcFinder func =
object
inherit Cil.nopCilVisitor

method! vglob glob =
match glob with
| Cil.GFun (fd, _) ->
if String.equal fd.svar.vname func then (
target_func := fd :: !target_func;
SkipChildren)
else Cil.SkipChildren
| _ -> Cil.SkipChildren
end

let extract_fundec func_name ast =
target_func := [];
let vis = new funcFinder func_name in
Cil.visitCilFile vis ast;
List.hd_exn !target_func

let insert_var_dec v =
let func_dec = List.hd_exn !target_func in
Cil.makeLocalVar func_dec v.Cil.vname v.Cil.vtype |> ignore

let mk_patron_tmp_var v =
if Hashtbl.mem vdec_map v.Cil.vname then
let new_vname = Hashtbl.find_exn vdec_map v.Cil.vname in
Cil.makeVarinfo false new_vname v.Cil.vtype
else
let new_vname = "__patron_tmp" ^ string_of_int !patron_tmp_var_cnt in
patron_tmp_var_cnt := !patron_tmp_var_cnt + 1;
Hashtbl.add_exn vdec_map ~key:v.Cil.vname ~data:new_vname;
Cil.makeLocalVar (List.hd_exn !target_func) new_vname v.Cil.vtype

let transform_lval lv fundec =
match lv with
| Cil.Var v, off -> (
let v' =
if Str.string_match (Str.regexp ".*__cil_tmp.*") v.Cil.vname 0 then
Some (mk_patron_tmp_var v)
else
List.find
~f:(fun v' -> String.equal v.vname v'.Cil.vname)
fundec.Cil.slocals
in
match v' with
| Some v' -> (Cil.Var v', off)
| None ->
if not (Hashtbl.mem vdec_map v.Cil.vname) then (
insert_var_dec v;
Hashtbl.add_exn vdec_map ~key:v.Cil.vname ~data:v.Cil.vname);
lv)
| _ -> lv

let rec transform_exp e fundec =
match e with
| Cil.Lval lv -> Cil.Lval (transform_lval lv fundec)
| Cil.CastE (t, e) -> Cil.CastE (t, transform_exp e fundec)
| Cil.BinOp (b, e1, e2, t) ->
Cil.BinOp (b, transform_exp e1 fundec, transform_exp e2 fundec, t)
| Cil.UnOp (u, e, t) -> Cil.UnOp (u, transform_exp e fundec, t)
| _ -> e

let transform_instr i fundec =
match i with
| Cil.Set (lv, e, loc) ->
let lv' = transform_lval lv fundec in
let e' = transform_exp e fundec in
Cil.Set (lv', e', loc)
| Cil.Call (lv, e, el, loc) ->
let lv' = Option.map ~f:(fun lv -> transform_lval lv fundec) lv in
let e' = transform_exp e fundec in
let el' = List.map ~f:(fun e -> transform_exp e fundec) el in
Cil.Call (lv', e', el', loc)
| _ -> i

let transform_return e loc fundec =
match fundec.Cil.svar.vtype with
| Cil.TVoid _ -> Cil.Return (None, loc)
| Cil.TInt _ ->
if Option.is_none e then
Cil.Return
( Some (Cil.Const (Cil.CInt64 (Int64.of_int (-1), Cil.IInt, None))),
loc )
else Cil.Return (e, loc)
| _ -> Cil.Return (e, loc)

let rec transform_stmt s fundec =
match s.Cil.skind with
| Cil.Instr instrs ->
let instrs' = List.map ~f:(fun i -> transform_instr i fundec) instrs in
{ s with skind = Cil.Instr instrs' }
| Cil.Return (e, loc) -> { s with skind = transform_return e loc fundec }
| Cil.If (e, tb, fb, loc) ->
let e' = transform_exp e fundec in
let tb'_stmts =
List.fold_left
~f:(fun acc s -> transform_stmt s fundec :: acc)
~init:[] tb.bstmts
in
let tb' = { tb with bstmts = List.rev tb'_stmts } in
let fb'_stmts =
List.fold_left
~f:(fun acc s -> transform_stmt s fundec :: acc)
~init:[] fb.bstmts
in
let fb' = { fb with bstmts = List.rev fb'_stmts } in
{ s with skind = Cil.If (e', tb', fb', loc) }
| _ -> s

let fit_stmt_to_donee s func_name donee =
let fun_dec = extract_fundec func_name donee in
transform_stmt s fun_dec

let is_patched = ref false

let partition mid stmts =
Expand Down Expand Up @@ -257,15 +375,29 @@ let apply_insert_stmt ?(update = false) func_name before after ss donee =
let very_after = List.hd after in
if Option.is_none very_before && Option.is_none very_after then
L.warn "apply_insert_stmt - cannot be patched";
let vis = new insertStmtVisitor ~update func_name very_before very_after ss in
let ss' =
List.fold_left
~f:(fun acc s -> fit_stmt_to_donee s func_name donee :: acc)
~init:[] ss
|> List.rev
in
let vis =
new insertStmtVisitor ~update func_name very_before very_after ss'
in
Cil.visitCilFile vis donee;
if not !is_patched then Logger.warn "failed to apply InsertStmt"
else L.info "Successfully applied InsertStmt at %s" func_name

let apply_update_stmt func_name s ss donee =
L.info "Applying UpdateStmt...";
is_patched := false;
let vis = new updateStmtfromFuncVisitor func_name s ss in
let ss' =
List.fold_left
~f:(fun acc s -> fit_stmt_to_donee s func_name donee :: acc)
~init:[] ss
|> List.rev
in
let vis = new updateStmtfromFuncVisitor func_name s ss' in
Cil.visitCilFile vis donee;
if not !is_patched then Logger.warn "failed to apply UpdateStmt"
else L.info "Successfully applied UpdateStmt at %s" func_name
Expand Down
4 changes: 2 additions & 2 deletions src/editFunction.ml
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,11 @@ let translate_update_callexp maps sol_map s s2 =
let new_s2 = translate_new_stmt maps sol_map s2.A.ast in
D.UpdateCallExp (target_func_name, new_s, new_s2)

let translate cand_donor maps out_dir target_alarm abs_diff =
let translate donor_name maps out_dir target_alarm abs_diff =
Logger.info "Translating patch...";
let sol_map = Hashtbl.create 1000 in
Hashtbl.reset sol_map;
let sm_file = F.asprintf "%s_%s_sol.map" cand_donor target_alarm in
let sm_file = F.asprintf "%s_%s_sol.map" donor_name target_alarm in
H.parse_map out_dir sm_file sol_map;
List.map
~f:(fun diff ->
Expand Down

0 comments on commit a8efab1

Please sign in to comment.