Skip to content

Commit 4daebb7

Browse files
authored
Protect against overflows in leaq N(src), dst (#407)
If N does not fit in signed 32 bits, `leaq` cannot be used and `mov; addq` must be used instead. This was already the case for `leaq` instructions produced by the Asmgen pass, but not for some `leaq` instructions produced by Asmexpand. Normally, assemblers should fail if the `leaq` offset is not representable, but this is not always the case (see issue #406). Fixes: #406
1 parent d2595e3 commit 4daebb7

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

x86/Asmexpand.ml

+17-12
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ let offset_addressing (Addrmode(base, ofs, cst)) delta =
109109
let linear_addr reg ofs = Addrmode(Some reg, None, Coq_inl ofs)
110110
let global_addr id ofs = Addrmode(None, None, Coq_inr(id, ofs))
111111

112+
(* Emit a 64-bit immediate add [dst <- src + imm]. *)
113+
114+
let emit_addimm64 dst src imm =
115+
if Op.offset_in_range imm then
116+
emit (Pleaq(dst, linear_addr src imm))
117+
else begin
118+
emit (Pmov_rr(dst, src)); emit (Paddq_ri(dst, Integers.Int64.repr imm))
119+
end
120+
112121
(* Translate a builtin argument into an addressing mode *)
113122

114123
let addressing_of_builtin_arg = function
@@ -289,9 +298,9 @@ let expand_builtin_va_start_elf64 r =
289298
emit (Pmovl_mr (linear_addr r _0z, RAX));
290299
emit (Pmovl_ri (RAX, coqint_of_camlint fp_offset));
291300
emit (Pmovl_mr (linear_addr r _4z, RAX));
292-
emit (Pleaq (RAX, linear_addr RSP (Z.of_uint64 overflow_arg_area)));
301+
emit_addimm64 RAX RSP (Z.of_uint64 overflow_arg_area);
293302
emit (Pmovq_mr (linear_addr r _8z, RAX));
294-
emit (Pleaq (RAX, linear_addr RSP (Z.of_uint64 reg_save_area)));
303+
emit_addimm64 RAX RSP (Z.of_uint64 reg_save_area);
295304
emit (Pmovq_mr (linear_addr r _16z, RAX))
296305

297306
let expand_builtin_va_start_win64 r =
@@ -302,7 +311,7 @@ let expand_builtin_va_start_win64 r =
302311
let ofs =
303312
Int64.(add !current_function_stacksize
304313
(mul 8L (of_int num_args))) in
305-
emit (Pleaq (RAX, linear_addr RSP (Z.of_uint64 ofs)));
314+
emit_addimm64 RAX RSP (Z.of_uint64 ofs);
306315
emit (Pmovq_mr (linear_addr r _0z, RAX))
307316

308317
(* FMA operations *)
@@ -550,10 +559,8 @@ let expand_instruction instr =
550559
emit (Psubl_ri (RSP, sz'));
551560
emit (Pcfi_adjust sz');
552561
(* Stack chaining *)
553-
let addr1 = linear_addr RSP (Z.of_uint (sz + 8)) in
554-
let addr2 = linear_addr RSP ofs_link in
555-
emit (Pleaq (RAX,addr1));
556-
emit (Pmovq_mr (addr2, RAX));
562+
emit_addimm64 RAX RSP (Z.of_uint (sz + 8));
563+
emit (Pmovq_mr (linear_addr RSP ofs_link, RAX));
557564
current_function_stacksize := Int64.of_int (sz + 8)
558565
end else if Archi.ptr64 then begin
559566
let (sz, save_regs) = sp_adjustment_elf64 sz in
@@ -563,16 +570,14 @@ let expand_instruction instr =
563570
emit (Pcfi_adjust sz');
564571
if save_regs >= 0 then begin
565572
(* Save the registers *)
566-
emit (Pleaq (R10, linear_addr RSP (Z.of_uint save_regs)));
573+
emit_addimm64 R10 RSP (Z.of_uint save_regs);
567574
emit (Pcall_s (intern_string "__compcert_va_saveregs",
568575
{sig_args = []; sig_res = Tvoid; sig_cc = cc_default}))
569576
end;
570577
(* Stack chaining *)
571578
let fullsz = sz + 8 in
572-
let addr1 = linear_addr RSP (Z.of_uint fullsz) in
573-
let addr2 = linear_addr RSP ofs_link in
574-
emit (Pleaq (RAX, addr1));
575-
emit (Pmovq_mr (addr2, RAX));
579+
emit_addimm64 RAX RSP (Z.of_uint fullsz);
580+
emit (Pmovq_mr (linear_addr RSP ofs_link, RAX));
576581
current_function_stacksize := Int64.of_int fullsz
577582
end else begin
578583
let sz = sp_adjustment_32 sz in

0 commit comments

Comments
 (0)