| |
| |
| |
| |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstring> |
| #include <cstdio> |
|
|
| |
| struct Range { |
| size_t offset, size; |
| Range(size_t o, size_t s) noexcept : offset(o), size(s) {} |
| inline size_t length() const noexcept { return offset + size; } |
| }; |
|
|
| static uint8_t* g_data; |
| static size_t g_size; |
|
|
| |
| static uint8_t* slice(Range range) noexcept { |
| if (range.length() > g_size) { |
| return nullptr; |
| } |
| return g_data + range.offset; |
| } |
|
|
| int main() { |
| setvbuf(stdout, NULL, _IONBF, 0); |
| g_size = 16; |
| g_data = new uint8_t[g_size]; |
| memset(g_data, 0x41, g_size); |
|
|
| |
| |
| |
| Range r(20, SIZE_MAX - 19); |
| printf("[*] buffer size = %zu\n", g_size); |
| printf("[*] attacker offset = %zu\n", r.offset); |
| printf("[*] attacker size = %zu\n", r.size); |
| printf("[*] length()=offset+size = %zu (wrapped past SIZE_MAX)\n", r.length()); |
| printf("[*] guard 'length() > size()': %zu > %zu -> %s\n", |
| r.length(), g_size, (r.length() > g_size) ? "REJECT" : "PASS (bypassed!)"); |
|
|
| uint8_t* p = slice(r); |
| if (p) { |
| printf("[!] slice() returned ptr %ld bytes past a %zu-byte buffer; dereferencing:\n", |
| (long)(p - g_data), g_size); |
| volatile uint8_t x = p[0]; |
| printf("[!] OOB read = 0x%02x (should NOT reach here under ASan)\n", x); |
| } |
| delete[] g_data; |
| return 0; |
| } |
|
|