Created
May 26, 2025 19:56
-
-
Save pavel-kirienko/f04058defcb21a9f20391e2faa5681d5 to your computer and use it in GitHub Desktop.
A simple utility class for debugging stack memory corruption.
This file contains hidden or 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
#include <cassert> | |
#include <cstdint> | |
#include <cstdlib> | |
namespace stack_canary | |
{ | |
/// Do not use this directly; see the StackCanary definition below. | |
template <std::size_t n_bytes, std::uint8_t seed = 0xC9> | |
class StackCanary_Impl final | |
{ | |
public: | |
constexpr StackCanary_Impl() noexcept | |
{ | |
for (std::size_t i = 0; i < n_bytes; ++i) | |
{ | |
data_[i] = reference(i); | |
} | |
ensure(); | |
} | |
StackCanary_Impl(const StackCanary_Impl&) = delete; | |
StackCanary_Impl& operator=(const StackCanary_Impl&) = delete; | |
StackCanary_Impl(StackCanary_Impl&&) = delete; | |
StackCanary_Impl& operator=(StackCanary_Impl&&) = delete; | |
~StackCanary_Impl() { ensure(); } | |
explicit operator bool() const volatile noexcept | |
{ | |
for (std::size_t i = 0; i < n_bytes; ++i) | |
{ | |
if (data_[i] != reference(i)) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
private: | |
void ensure() const volatile noexcept | |
{ | |
if (!*this) | |
{ | |
assert(false); | |
std::abort(); | |
} | |
} | |
static constexpr std::uint8_t reference(const size_t i) noexcept { return (seed + (i * 0xC9U)) & 0xFFU; } | |
volatile std::uint8_t data_[n_bytes]; | |
}; | |
/// A simple utility class for debugging stack memory corruption. | |
/// The dtor will invoke assert(false) and std::abort() if memory corruption is detected. | |
/// The canary is designed to have a 1-byte alignment. | |
/// Generate reference values for searching in binary dumps: | |
/// | |
/// >>> stage = lambda i: (0xC9 + (i * 0xC9)) & 0xFF | |
/// >>> bytes(map(stage, range(64))).hex() | |
template <std::size_t n_bytes = 64> | |
using StackCanary = volatile StackCanary_Impl<n_bytes>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment