From 3d8e67daac34c03f188e6ca15b3fe9e9ab07572b Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 6 Oct 2023 10:08:03 -0700 Subject: [PATCH] [ASan][Windows] Fix rip-relative instruction replacement The old code incorrectly checked what relative offsets were allowed. The correct check is that the offset from the target to the instruction pointer should be within $[-2^{31}, 2^{31})$; however, the check that was originally written was that the offset was within $[0, 2^{31})$. Negative offsets are certainly allowable (as long as they fit in 32 bits), and this change fixes that. --- .../lib/interception/interception_win.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index 23d26ea94b51a..d57afa3fda7bc 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -726,16 +726,22 @@ static bool CopyInstructions(uptr to, uptr from, size_t size) { size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset); if (!instruction_size) return false; - _memcpy((void*)(to + cursor), (void*)(from + cursor), + _memcpy((void *)(to + cursor), (void *)(from + cursor), (size_t)instruction_size); if (rel_offset) { - uptr delta = to - from; - uptr relocated_offset = *(u32*)(to + cursor + rel_offset) - delta; -#if SANITIZER_WINDOWS64 - if (relocated_offset + 0x80000000U >= 0xFFFFFFFFU) +# if SANITIZER_WINDOWS64 + // we want to make sure that the new relative offset still fits in 32-bits + // this will be untrue if relocated_offset \notin [-2**31, 2**31) + s64 delta = to - from; + s64 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta; + if (-0x8000'0000ll > relocated_offset || relocated_offset > 0x7FFF'FFFFll) return false; -#endif - *(u32*)(to + cursor + rel_offset) = relocated_offset; +# else + // on 32-bit, the relative offset will always be correct + s32 delta = to - from; + s32 relocated_offset = *(s32 *)(to + cursor + rel_offset) - delta; +# endif + *(s32 *)(to + cursor + rel_offset) = relocated_offset; } cursor += instruction_size; }