Skip to content

Commit 22f64f2

Browse files
Lef IoannidisCopilot
andcommitted
Fix UInt8/UInt16 comparison after wrapping arithmetic (#694)
Comparisons (Eq, Neq, Lt, Lte, Gt, Gte) on UInt8/UInt16 after wrapping arithmetic (add_mod, sub_mod, mul_mod, shift_left, xor, or, etc.) produced wrong C code. The uint32 intermediate from mk_arith was compared directly without masking back to the original width. For example, (255uy +%^ 1uy) = 0uy generated: (uint32_t)255 + (uint32_t)1 == 0 => 256 == 0 => false (WRONG) Fix: handle comparisons in mk_expr (not mk_arith) with a dedicated pattern that only widens+masks operands containing arithmetic subexpressions. Atomic operands (variables, field accesses, etc.) are compared at their native width without unnecessary casts. Now generates: simple: a == b (no casts) arith: ((uint32_t)a + (uint32_t)b & 0xFFU) == c (only arith side) Fixes #694. Also fixes #689, #691, #692, #693 (same root cause). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d859556 commit 22f64f2

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

lib/AstToCStar.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,24 @@ and mk_expr env in_stmt under_initializer_list e =
417417
else
418418
e'
419419

420+
| EApp ({ node = EOp (op, w); _ }, [ e1; e2 ])
421+
when Constant.is_comp_op op && (w = K.UInt8 || w = K.UInt16) ->
422+
(* Comparisons on narrow unsigned types: only widen+mask operands that
423+
contain arithmetic. Atomic operands (variables, field accesses, etc.)
424+
are compared at their native width without unnecessary casts. *)
425+
let needs_arith e = match e.node with
426+
| EApp ({ node = EOp (op, w); _ }, _) -> is_integer_arith op w
427+
| _ -> false
428+
in
429+
let mk_cmp_operand e =
430+
if needs_arith e then
431+
let e', a, _ = mk_arith env e in
432+
if a then e' else mask w e'
433+
else
434+
mk_expr env false e
435+
in
436+
CStar.Call (Op op, [ mk_cmp_operand e1; mk_cmp_operand e2 ])
437+
420438
| EApp (e, es) ->
421439
(* Functions that only take a unit take no argument. *)
422440
let t, _ = flatten_arrow e.typ in

0 commit comments

Comments
 (0)