forked from OSchip/llvm-project
[asan] Don't assert that a target is within 2GB on 32-bit Windows
Summary: In a 32-bit address space, PC-relative jump targets are wrapped, so a direct branch at 0x90000001 can reach address 0x10000000 with a displacement of 0x7FFFFFFFF. This can happen in applications, such as Chrome, that are linked with /LARGEADDRESSAWARE. Reviewers: etienneb Subscribers: mgorny, llvm-commits Differential Revision: https://reviews.llvm.org/D26650 llvm-svn: 286997
This commit is contained in:
parent
b17efcbcc5
commit
0d7c42c7ab
|
@ -148,10 +148,16 @@ static void InterceptionFailed() {
|
|||
}
|
||||
|
||||
static bool DistanceIsWithin2Gig(uptr from, uptr target) {
|
||||
#if SANITIZER_WINDOWS64
|
||||
if (from < target)
|
||||
return target - from <= (uptr)0x7FFFFFFFU;
|
||||
else
|
||||
return from - target <= (uptr)0x80000000U;
|
||||
#else
|
||||
// In a 32-bit address space, the address calculation will wrap, so this check
|
||||
// is unnecessary.
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uptr GetMmapGranularity() {
|
||||
|
|
|
@ -29,6 +29,7 @@ else()
|
|||
endif()
|
||||
if(MSVC)
|
||||
list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gcodeview)
|
||||
list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -Wl,-largeaddressaware)
|
||||
endif()
|
||||
list(APPEND INTERCEPTION_TEST_LINK_FLAGS_COMMON -g)
|
||||
|
||||
|
|
|
@ -204,7 +204,29 @@ const u8 kUnpatchableCode6[] = {
|
|||
|
||||
// A buffer holding the dynamically generated code under test.
|
||||
u8* ActiveCode;
|
||||
size_t ActiveCodeLength = 4096;
|
||||
const size_t ActiveCodeLength = 4096;
|
||||
|
||||
int InterceptorFunction(int x);
|
||||
|
||||
/// Allocate code memory more than 2GB away from Base.
|
||||
u8 *AllocateCode2GBAway(u8 *Base) {
|
||||
// Find a 64K aligned location after Base plus 2GB.
|
||||
size_t TwoGB = 0x80000000;
|
||||
size_t AllocGranularity = 0x10000;
|
||||
Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
|
||||
|
||||
// Check if that location is free, and if not, loop over regions until we find
|
||||
// one that is.
|
||||
MEMORY_BASIC_INFORMATION mbi = {};
|
||||
while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
|
||||
if (mbi.State & MEM_FREE) break;
|
||||
Base += mbi.RegionSize;
|
||||
}
|
||||
|
||||
// Allocate one RWX page at the free location.
|
||||
return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void LoadActiveCode(
|
||||
|
@ -212,11 +234,8 @@ static void LoadActiveCode(
|
|||
uptr *entry_point,
|
||||
FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
|
||||
if (ActiveCode == nullptr) {
|
||||
ActiveCode =
|
||||
(u8*)::VirtualAlloc(nullptr, ActiveCodeLength,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
ASSERT_NE(ActiveCode, nullptr);
|
||||
ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
|
||||
ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
|
||||
}
|
||||
|
||||
size_t position = 0;
|
||||
|
|
Loading…
Reference in New Issue