Skip to content

Commit 13d0e37

Browse files
committed
Added flag and map comparison.
1 parent 3125be5 commit 13d0e37

File tree

6 files changed

+86
-50
lines changed

6 files changed

+86
-50
lines changed

wp/plugin/lib/analysis.ml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,21 @@ let single (bap_ctx : ctxt) (z3_ctx : Z3.context) (var_gen : Env.var_gen)
259259
Printf.printf "\nSub:\n%s\n%!" (Sub.to_string main_sub);
260260
{ pre = pre; orig = env, main_sub; modif = env, main_sub }
261261

262+
let check_syntax_equality (bap_ctx : ctxt)
263+
(p : Params.t) (file1 : string) (file2 : string) : bool =
264+
(* TODO replace with param flag *)
265+
if p.syntax_equality then
266+
let prog1, _ = Utils.read_program bap_ctx
267+
~loader:Utils.loader ~filepath:file1 in
268+
let prog2, _ = Utils.read_program bap_ctx
269+
~loader:Utils.loader ~filepath:file2 in
270+
let subs1 = Term.enum sub_t prog1 in
271+
let subs2 = Term.enum sub_t prog2 in
272+
let main_sub1 = Utils.find_func_err subs1 p.func in
273+
let main_sub2 = Utils.find_func_err subs2 p.func in
274+
Eq.exist_isomorphism main_sub1 main_sub2
275+
else false
276+
262277
(* Runs a comparative analysis. *)
263278
let comparative (bap_ctx : ctxt) (z3_ctx : Z3.context) (var_gen : Env.var_gen)
264279
(p : Params.t) (file1 : string) (file2 : string) : combined_pre =
@@ -270,8 +285,6 @@ let comparative (bap_ctx : ctxt) (z3_ctx : Z3.context) (var_gen : Env.var_gen)
270285
let subs2 = Term.enum sub_t prog2 in
271286
let main_sub1 = Utils.find_func_err subs1 p.func in
272287
let main_sub2 = Utils.find_func_err subs2 p.func in
273-
let syntactically_equal = Eq.cmp_overall main_sub1 main_sub2 in
274-
Printf.printf "\nTHE SUBS ARE EQUAL: %b\n" syntactically_equal;
275288
let stack_range = Utils.update_stack ~base:p.stack_base ~size:p.stack_size in
276289
let env2, pointer_vars_2 =
277290
let to_inline2 = Utils.match_inline p.inline subs2 in
@@ -361,8 +374,12 @@ let run (p : Params.t) (files : string list) (bap_ctx : ctxt)
361374
single bap_ctx z3_ctx var_gen p file
362375
|> check_pre p z3_ctx
363376
| [file1; file2] ->
364-
comparative bap_ctx z3_ctx var_gen p file1 file2
365-
|> check_pre p z3_ctx
377+
begin
378+
match check_syntax_equality bap_ctx p file1 file2 with
379+
| false ->
380+
comparative bap_ctx z3_ctx var_gen p file1 file2 |> check_pre p z3_ctx
381+
| true -> Ok ()
382+
end
366383
| _ ->
367384
let err =
368385
Printf.sprintf "WP can only analyze one binary for a single analysis or \

wp/plugin/lib/equality.ml

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module TidSet = Set.Make(Tid)
1313

1414
module TidMap = Map.Make(Tid)
1515
module VarMap = Map.Make(Var)
16+
module VarSet = Set.Make(Var)
1617
module TidTupleMap = Map.Make(struct type t = Tid.t * Tid.t [@@deriving sexp, compare] end)
1718

1819
type varToVarMap = Var.t VarMap.t
@@ -296,11 +297,33 @@ let check_isomorphism
296297
let blk2 = TidMap.find_exn tid_to_blk2 tid2 in
297298
compare_blk_tid_only graph blk1 blk2)
298299

299-
let rec get_isomorphism (candidate_map : TidSet.t TidMap.t) (used_set : TidSet.t) (node_stack : (blk term) list)
300-
(graph : Tid.t TidMap.t) (tid_to_blk1 : (blk term) TidMap.t) (tid_to_blk2 : (blk term) TidMap.t): (Tid.t TidMap.t) option =
300+
let merge_maps (merged_map : varToVarMap) (new_map : varToVarMap) : varToVarMap option =
301+
let new_merged_map = VarMap.merge merged_map new_map
302+
~f:(fun ~key:_key v ->
303+
match v with
304+
| `Left v1 -> Some v1
305+
| `Right v2 -> Some v2
306+
| `Both (v1, v2) -> if Var.equal v1 v2 then Some v1 else None)
307+
in
308+
let get_keys = (fun m -> VarMap.keys m |> VarSet.of_list) in
309+
let expected_len = VarSet.union (get_keys merged_map) (get_keys new_map) |> VarSet.length in
310+
let actual_len = VarMap.keys new_merged_map |> List.length in
311+
match actual_len = expected_len with
312+
false -> None
313+
| true -> Some new_merged_map
314+
315+
let rec get_isomorphism
316+
(candidate_map : TidSet.t TidMap.t) (used_set : TidSet.t)
317+
(node_stack : (blk term) list) (graph : Tid.t TidMap.t)
318+
(tid_to_blk1 : (blk term) TidMap.t) (tid_to_blk2 : (blk term) TidMap.t)
319+
(var_maps : varToVarMap TidTupleMap.t) (merged_map : varToVarMap) :
320+
(Tid.t TidMap.t) option =
301321
let node = List.hd node_stack in
302322
match node with
303-
| None -> if check_isomorphism graph tid_to_blk1 tid_to_blk2 then Some graph else None
323+
| None ->
324+
if check_isomorphism graph tid_to_blk1 tid_to_blk2
325+
then Some graph
326+
else None
304327
| Some node ->
305328
let tid = Term.tid node in
306329
match TidMap.find candidate_map tid with
@@ -312,58 +335,41 @@ let rec get_isomorphism (candidate_map : TidSet.t TidMap.t) (used_set : TidSet.t
312335
(* cannot be empty *)
313336
let node_stack = List.tl_exn node_stack in
314337
let graph = TidMap.update graph tid ~f:(fun _ -> tid_mapped_to) in
315-
get_isomorphism candidate_map used_set node_stack graph tid_to_blk1 tid_to_blk2)
338+
(* TODO change this to a map lookup *)
339+
TidTupleMap.find var_maps (tid, tid_mapped_to) >>=
340+
fun new_map ->
341+
merge_maps merged_map new_map >>=
342+
fun merged_map ->
343+
get_isomorphism candidate_map used_set node_stack
344+
graph tid_to_blk1 tid_to_blk2 var_maps merged_map)
316345
| None -> None
317346

347+
let get_length cfg : int =
348+
let f = ( fun node acc ->
349+
let lbl = get_label node in
350+
let def_len = Term.enum def_t lbl |> Sequence.to_list |> List.length in
351+
let jmp_len = Term.enum jmp_t lbl |> Sequence.to_list |> List.length in
352+
acc + def_len + jmp_len
353+
) in
354+
BFS.fold f 0 cfg
355+
318356
let exist_isomorphism (sub1: Sub.t) (sub2 : Sub.t) : bool =
319357
let cfg1, cfg2 = Sub.to_cfg sub1, Sub.to_cfg sub2 in
358+
printf "\nLENGTH IS: %d\n" (get_length cfg1);
320359
let tid_to_blk1, tid_to_blk2 = get_node_maps cfg1 cfg2 in
321360
(* the variable mappings on a per-block basis are not actually used *)
322-
let tid_map, _var_maps = compare_blocks sub1 sub2 in
361+
let tid_map, var_maps = compare_blocks sub1 sub2 in
362+
let _ = printf "PERCENTAGE_IDENTICAL_BLOCKS_IS: %.4f\n" (((List.length (TidMap.keys tid_map)) |> float_of_int) /. ((List.length (TidMap.keys tid_to_blk1)) |> float_of_int)) in
323363
(* List.iter (TidMap.keys tid_map) ~f:(fun key -> printf "TID MAP: %s\n" (Tid.to_string key)) ; *)
324364
let used_set = TidSet.empty in
325365
let node_stack = TidMap.data tid_to_blk1 in
326366
let node2_stack = TidMap.data tid_to_blk2 in
327367
let graph = TidMap.empty in
328-
printf "BLOCK LENGTH: %d" (List.length node_stack);
368+
printf "BLOCK LENGTH: %d\n" (List.length node_stack);
329369
(* short circuit if we already know that the length does not match *)
330370
if (List.length node_stack) = (List.length node2_stack) then
331-
match get_isomorphism tid_map used_set node_stack graph tid_to_blk1 tid_to_blk2 with
371+
match get_isomorphism tid_map used_set node_stack graph tid_to_blk1 tid_to_blk2 var_maps VarMap.empty with
332372
| None -> false
333-
| Some _x -> true
373+
| Some _x ->
374+
printf "Blocks are syntactically equal! Not performing WP analysis.\nUNSAT!\n"; true
334375
else false
335-
336-
(* let evaluator_overall node1 cur_res =
337-
* match cur_res with
338-
* | Some (seen_set, v_map, cfg2) ->
339-
* let inner_evaluator =
340-
* (fun (node2 : Bap.Std.Graphs.Ir.Node.t) (found_match, seen_set, v_map) ->
341-
* let blk2 = get_label node2 in
342-
* let tid2 = Term.tid blk2 in
343-
* match found_match with
344-
* | true -> true, seen_set, v_map
345-
* | false ->
346-
* (\* if already matched, then don't consider again *\)
347-
* if TidSet.exists seen_set ~f:(fun a -> a = tid2) then false, seen_set, v_map
348-
* (\* otherwise, perform comparison *\)
349-
* else
350-
* match compare_block (get_label node1) blk2 v_map with
351-
* | Some v_map_updated ->
352-
* true, TidSet.union seen_set (TidSet.singleton tid2), v_map_updated
353-
* | None -> false, seen_set, v_map) in
354-
* let r, s, m = BFS.fold inner_evaluator (false, seen_set, v_map) cfg2 in
355-
* if r then
356-
* Some (s, m, cfg2)
357-
* else None
358-
* | None -> None
359-
*
360-
* (\* performs the overarching comparison for exact syntactic equality between subs*\)
361-
* let cmp_overall (sub1 : Sub.t) (sub2 : Sub.t) : bool =
362-
* let cfg1, cfg2 = Sub.to_cfg sub1, Sub.to_cfg sub2 in
363-
* let seen_set = TidSet.empty in
364-
* let v_map = VarMap.empty in
365-
* let r = BFS.fold evaluator_overall (Some (seen_set, v_map, cfg2)) cfg1 in
366-
* match r with
367-
* | Some _ -> true
368-
* | None -> false *)
369-

wp/plugin/lib/parameters.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ type t = {
4747
debug : string list;
4848
stack_base : int option;
4949
stack_size : int option;
50-
show : string list
50+
syntax_equality : bool;
51+
show : string list;
5152
}
5253

5354
(* Ensures the user inputted a function for analysis. *)

wp/plugin/lib/parameters.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ type t = {
5050
debug : string list;
5151
stack_base : int option;
5252
stack_size : int option;
53-
show : string list
53+
syntax_equality : bool;
54+
show : string list;
5455
}
5556

5657
(** [validate flags files] ensures the user inputted the appropriate flags for

wp/plugin/wp.ml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ let stack_size = Cmd.parameter Typ.(some int) "stack-size"
180180
~doc:{|Sets the size of the stack, which should be denoted in bytes. By
181181
default, the size of the stack is 0x800000 which is 8MB.|}
182182

183+
let syntax_equality = Cmd.flag "syntax-equality"
184+
~doc:{| Short-circuits WP and returns UNSAT if the functions
185+
are syntactically equal. Use with caution; the comparison must
186+
be testing for function equality in the same sense as syntactic
187+
equality. This is currently found with the mem_offset flag and
188+
pointer flag enabled. Only applicable in the comparative case. |}
189+
183190
let grammar = Cmd.(
184191
args
185192
$ func
@@ -200,6 +207,7 @@ let grammar = Cmd.(
200207
$ show
201208
$ stack_base
202209
$ stack_size
210+
$ syntax_equality
203211
$ files)
204212

205213
(* The callback run when the command is invoked from the command line. *)
@@ -222,6 +230,7 @@ let callback
222230
(show : string list)
223231
(stack_base : int option)
224232
(stack_size : int option)
233+
(syntax_equality : bool)
225234
(files : string list)
226235
(ctxt : ctxt) =
227236
let params = Parameters.({
@@ -242,7 +251,8 @@ let callback
242251
debug = debug;
243252
show = show;
244253
stack_base = stack_base;
245-
stack_size = stack_size
254+
stack_size = stack_size;
255+
syntax_equality = syntax_equality;
246256
})
247257
in
248258
Parameters.validate params files >>= fun () ->

wp/resources/sample_binaries/syntax_equality/run_wp.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ run_unsat () {
1212
--num-unroll=0 \
1313
--no-byteweight \
1414
--mem-offset \
15+
--syntax-equality \
1516
-- main_1 main_2
1617
}
1718

0 commit comments

Comments
 (0)