Skip to content

Commit 3682860

Browse files
authored
relaxes the Apply.binop function to allow not well-typed operations (#1422)
We are not changing the typing rules of BIL or Core Theory, but providing a well-defined behavior for application of binary operations on bitvectors with unequal lengths. Before that, the behavior was undefined and the precondition of the function was clearly specifying that the inputs should be of equal lengths. The new behavior is to promote words to the equal length, (much like in C, which implicitly coerces the narrow type to the wider type). The motivation is simple. It is hard to ensure this precondition in general. Yes, our lifters produce well-typed code, so there are no issues when we interpret code from the lifters. But we also have a lot of different interpreters, extensible via primitives. And those interpreters sometimes don't have any means (or at least efficient means) to ensure that all binary operations have matching widths. A concrete example of such interpreter is Veri that is used for bi-interpretation of traces and BIL programs for verification. Sometimes, the tracers organically produce ill-typed code, as they rely on their own typing rules. For example, qemu-based tracer just represent every register (including flags) and every number (including bools) with a word-sized bitvector. We still want to be able to perform calculations on such inputs and, to be honest, the results are quite well-defined, no hacks required. In other words, this change tries to follow the robustness principle, i.e., "be conservative in what you do, be liberal in what you accept from others". Our lifters, i.e., the code that we produce, are still much conservative, but our interpreters tend to be more liberal and understand even the ill-typed code, especially if this code has clear semantics.
1 parent e52449e commit 3682860

File tree

2 files changed

+17
-12
lines changed

2 files changed

+17
-12
lines changed

lib/bap/bap.mli

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,20 +2444,27 @@ module Std : sig
24442444
*)
24452445
module Apply : sig
24462446

2447-
(** [binop op x y] applies the binary operation [op] to [x] and
2448-
[y].
2449-
precondition: the expression [BinOp(op,Int x,Int y)] shall be well-typed.*)
2447+
(** [binop op x y] applies [op] to [x] and [y].
2448+
2449+
@before 2.5.0 precondition: the expression [BinOp(op,Intx,Int y)]
2450+
shall be well-typed.
2451+
2452+
@after 2.5.0 if [x] and [y] have different widths then they
2453+
are extended to the same width, which is the width of the
2454+
largest operand. If an operator is signed, then it will be
2455+
correctly sign-extended.
2456+
*)
24502457
val binop : binop -> word -> word -> word
24512458

2452-
(** [unop op x] applies the unary operation [op] to [x].
2453-
precondition: the expression [Unop(op,Int x)] shall be
2454-
well-typed. *)
2459+
(** [unop op x] applies the unary operation [op] to [x]. *)
24552460
val unop : unop -> word -> word
24562461

24572462
(** [cast t s x] casts [x] using the cast type [t] to the given
24582463
size [s].
2464+
24592465
precondition: the expression [Cast(t,s,Int x)] shall be
2460-
well-typed. *)
2466+
well-typed.
2467+
*)
24612468
val cast : cast -> int -> word -> word
24622469
end
24632470

lib/bap_types/bap_helpers.ml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,9 @@ module Apply = struct
127127

128128
let binop op u v =
129129
let open Word in
130-
if Int.(bitwidth u <> bitwidth v) && not (is_shift op)
131-
then failwithf "binop type error - %s %s %s"
132-
(to_string u)
133-
(Bap_exp.Binop.string_of_binop op)
134-
(to_string v) ();
130+
let hi = Int.(max (bitwidth u) (bitwidth v) - 1) in
131+
let u = extract_exn ~hi u
132+
and v = extract_exn ~hi v in
135133
match op with
136134
| PLUS -> u + v
137135
| MINUS -> u - v

0 commit comments

Comments
 (0)