-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ASan][Windows] Fix rip-relative instruction replacement #68432
Conversation
@llvm/pr-subscribers-compiler-rt-sanitizer ChangesThe 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 [-231, 231); 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. Full diff: https://github.com/llvm/llvm-project/pull/68432.diff 1 Files Affected:
diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp
index 23d26ea94b51a66..4f2a51e1adbc6e0 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)
+ // 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;
+#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
- *(u32*)(to + cursor + rel_offset) = relocated_offset;
+ *(s32 *)(to + cursor + rel_offset) = relocated_offset;
}
cursor += instruction_size;
}
|
This comment was marked as resolved.
This comment was marked as resolved.
67dfb84
to
f855b36
Compare
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.
f855b36
to
3d8e67d
Compare
@@ -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), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this clang-formated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.
uptr relocated_offset = *(u32*)(to + cursor + rel_offset) - delta; | ||
#if SANITIZER_WINDOWS64 | ||
if (relocated_offset + 0x80000000U >= 0xFFFFFFFFU) | ||
# if SANITIZER_WINDOWS64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe if constexpr (SANITIZER_WINDOWS64)
to compile it always
// 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you can use same code if use s64/s32 -> sptr
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.