x64 backend: fix condition-code used for part of explicit heap check.
A dynamic heap address computation may create up to two conditional branches: the usual bounds-check, but also (in some cases) an offset-addition overflow check. The x64 backend had reversed the condition code for this check, resulting in an always-trapping execution for a valid offset. I'm somewhat surprised this has existed so long, but I suppose the particular conditions (large offset, small offset guard, dynamic heap) have been somewhat rare in our testing so far. Found via fuzzing in #2453.
This commit is contained in:
@@ -92,15 +92,15 @@ impl MachBackend for X64Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned_add_overflow_condition(&self) -> IntCC {
|
fn unsigned_add_overflow_condition(&self) -> IntCC {
|
||||||
// Unsigned `>=`; this corresponds to the carry flag set on x86, which happens on
|
// Unsigned `<`; this corresponds to the carry flag set on x86, which
|
||||||
// overflow of an add.
|
// indicates an add has overflowed.
|
||||||
IntCC::UnsignedGreaterThanOrEqual
|
IntCC::UnsignedLessThan
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned_sub_overflow_condition(&self) -> IntCC {
|
fn unsigned_sub_overflow_condition(&self) -> IntCC {
|
||||||
// unsigned `>=`; this corresponds to the carry flag set on x86, which happens on
|
// unsigned `<`; this corresponds to the carry flag set on x86, which
|
||||||
// underflow of a subtract (carry is borrow for subtract).
|
// indicates a sub has underflowed (carry is borrow for subtract).
|
||||||
IntCC::UnsignedGreaterThanOrEqual
|
IntCC::UnsignedLessThan
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
|
|||||||
23
cranelift/filetests/filetests/isa/x64/heap.clif
Normal file
23
cranelift/filetests/filetests/isa/x64/heap.clif
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
test compile
|
||||||
|
target x86_64
|
||||||
|
feature "experimental_x64"
|
||||||
|
|
||||||
|
function %f(i32, i64 vmctx) -> i64 {
|
||||||
|
gv0 = vmctx
|
||||||
|
gv1 = load.i64 notrap aligned gv0+0
|
||||||
|
gv2 = load.i32 notrap aligned gv0+8
|
||||||
|
heap0 = dynamic gv1, bound gv2, offset_guard 0x1000, index_type i32
|
||||||
|
|
||||||
|
block0(v0: i32, v1: i64):
|
||||||
|
|
||||||
|
v2 = heap_addr.i64 heap0, v0, 0x8000
|
||||||
|
; check: movl 8(%rsi), %r12d
|
||||||
|
; nextln: movq %rdi, %r13
|
||||||
|
; nextln: addl $$32768, %r13d
|
||||||
|
; nextln: jnb ; ud2 heap_oob ;
|
||||||
|
; nextln: cmpl %r12d, %r13d
|
||||||
|
; nextln: jbe label1; j label2
|
||||||
|
; check: Block 1:
|
||||||
|
|
||||||
|
return v2
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user