-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Roll forward poisoned pointer API and fix portability issues.
Also, return the middle of the poisoned block. PiperOrigin-RevId: 651119057 Change-Id: Iae0fc3dcb40e32cd449f469d9b8d62c37f3773f4
- Loading branch information
1 parent
bb50cad
commit 5b6285e
Showing
6 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2024 The Abseil Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "absl/base/internal/poison.h" | ||
|
||
#include <cstdlib> | ||
|
||
#include "absl/base/config.h" | ||
#include "absl/base/internal/direct_mmap.h" | ||
|
||
#ifndef _WIN32 | ||
#include <unistd.h> | ||
#endif | ||
|
||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) | ||
#include <sanitizer/asan_interface.h> | ||
#elif defined(ABSL_HAVE_MEMORY_SANITIZER) | ||
#include <sanitizer/msan_interface.h> | ||
#elif defined(ABSL_HAVE_MMAP) | ||
#include <sys/mman.h> | ||
#elif defined(_WIN32) | ||
#include <windows.h> | ||
#endif | ||
|
||
namespace absl { | ||
ABSL_NAMESPACE_BEGIN | ||
namespace base_internal { | ||
|
||
namespace { | ||
|
||
size_t GetPageSize() { | ||
#ifdef _WIN32 | ||
SYSTEM_INFO system_info; | ||
GetSystemInfo(&system_info); | ||
return system_info.dwPageSize; | ||
#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__) | ||
return getpagesize(); | ||
#else | ||
return static_cast<size_t>(sysconf(_SC_PAGESIZE)); | ||
#endif | ||
} | ||
|
||
} // namespace | ||
|
||
void* InitializePoisonedPointerInternal() { | ||
const size_t block_size = GetPageSize(); | ||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) | ||
void* data = malloc(block_size); | ||
ASAN_POISON_MEMORY_REGION(data, block_size); | ||
#elif defined(ABSL_HAVE_MEMORY_SANITIZER) | ||
void* data = malloc(block_size); | ||
__msan_poison(data, block_size); | ||
#elif defined(ABSL_HAVE_MMAP) | ||
void* data = DirectMmap(nullptr, block_size, PROT_NONE, | ||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
if (data == MAP_FAILED) return GetBadPointerInternal(); | ||
#elif defined(_WIN32) | ||
void* data = VirtualAlloc(nullptr, block_size, MEM_RESERVE | MEM_COMMIT, | ||
PAGE_NOACCESS); | ||
if (data == nullptr) return GetBadPointerInternal(); | ||
#else | ||
return GetBadPointerInternal(); | ||
#endif | ||
// Return the middle of the block so that dereferences before and after the | ||
// pointer will both crash. | ||
return static_cast<char*>(data) + block_size / 2; | ||
} | ||
|
||
} // namespace base_internal | ||
ABSL_NAMESPACE_END | ||
} // namespace absl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2024 The Abseil Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef ABSL_BASE_INTERNAL_POISON_H_ | ||
#define ABSL_BASE_INTERNAL_POISON_H_ | ||
|
||
#include <cstdint> | ||
|
||
#include "absl/base/config.h" | ||
|
||
namespace absl { | ||
ABSL_NAMESPACE_BEGIN | ||
namespace base_internal { | ||
|
||
inline void* GetBadPointerInternal() { | ||
// A likely bad pointer. Pointers are required to have high bits that are all | ||
// zero or all one for certain 64-bit CPUs. This pointer value will hopefully | ||
// cause a crash on dereference and also be clearly recognizable as invalid. | ||
constexpr uint64_t kBadPtr = 0xBAD0BAD0BAD0BAD0; | ||
auto ret = reinterpret_cast<void*>(static_cast<uintptr_t>(kBadPtr)); | ||
#ifndef _MSC_VER // MSVC doesn't support inline asm with `volatile`. | ||
// Try to prevent the compiler from optimizing out the undefined behavior. | ||
asm volatile("" : : "r"(ret) :); // NOLINT | ||
#endif | ||
return ret; | ||
} | ||
|
||
void* InitializePoisonedPointerInternal(); | ||
|
||
inline void* get_poisoned_pointer() { | ||
#if defined(NDEBUG) && !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ | ||
!defined(ABSL_HAVE_MEMORY_SANITIZER) | ||
// In optimized non-sanitized builds, avoid the function-local static because | ||
// of the codegen and runtime cost. | ||
return GetBadPointerInternal(); | ||
#else | ||
// Non-optimized builds may use more robust implementation. Note that we can't | ||
// use a static global because Chromium doesn't allow non-constinit globals. | ||
static void* ptr = InitializePoisonedPointerInternal(); | ||
return ptr; | ||
#endif | ||
} | ||
|
||
} // namespace base_internal | ||
ABSL_NAMESPACE_END | ||
} // namespace absl | ||
|
||
#endif // ABSL_BASE_INTERNAL_POISON_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2024 The Abseil Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "absl/base/internal/poison.h" | ||
|
||
#include <iostream> | ||
|
||
#include "gtest/gtest.h" | ||
#include "absl/base/config.h" | ||
|
||
namespace absl { | ||
ABSL_NAMESPACE_BEGIN | ||
namespace base_internal { | ||
namespace { | ||
|
||
TEST(PoisonTest, CrashesOnDereference) { | ||
#ifdef __ANDROID__ | ||
GTEST_SKIP() << "On Android, poisoned pointer dereference times out instead " | ||
"of crashing."; | ||
#endif | ||
int* poisoned_ptr = static_cast<int*>(get_poisoned_pointer()); | ||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *poisoned_ptr, ""); | ||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr - 10), ""); | ||
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr + 10), ""); | ||
} | ||
|
||
} // namespace | ||
} // namespace base_internal | ||
ABSL_NAMESPACE_END | ||
} // namespace absl |