#include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// sigjmp_buf fault_jmp; __attribute__((no_sanitize_address)) bool has_fault (const volatile char* addr) { if (sigsetjmp (fault_jmp, 1) == 0) { *addr; return false; } else { return true; } } //----------------------------------------------------------------------------- static bool fault_seen; static void *fault_address; __attribute__((no_sanitize_address)) void segv_handler (int num, siginfo_t *info, void *cookie) { CHECK_EQ (num, SIGSEGV); (void)num; (void)cookie; fault_seen = true; fault_address = info->si_addr; siglongjmp (fault_jmp, SIGSEGV); } /////////////////////////////////////////////////////////////////////////////// int main (void) { cruft::TAP::logger tap; #if 0 // setup a trap to record SEGV events struct sigaction newhandler {}; newhandler.sa_sigaction = segv_handler; newhandler.sa_flags = SA_SIGINFO; cruft::posix::error::try_call ( sigaction, SIGSEGV, &newhandler, nullptr ); // initialise a partially unmapped buffer. the tests assume that the // window is substantially less than half the capacity (so that probing // the centre doesn't trigger a mapping overlapping the end). constexpr size_t CAPACITY = 16 * 1024 * 1024; cruft::buffer::paged buffer (CAPACITY); typedef decltype(buffer)::value_type value_type; const value_type *first = buffer.begin (); const value_type *last = buffer.end () - 1; const value_type *centre = buffer.begin () + buffer.capacity () / 2; const value_type *window = centre + buffer.window () - 1; // ensure correct initial mappings tap.expect (!has_fault (first), "first is initially valid"); tap.expect ( has_fault (last), "last is intially invalid"); // allocate half the buffer and check mappings buffer.commit ({ first, last }); tap.expect (!has_fault (first), "first remains valid after commit"); tap.expect (!has_fault (centre), "centre is valid after partial commit"); tap.expect (!has_fault (window), "centre window is valid after partial commit"); tap.expect ( has_fault (last), "last is invalid after partial commit"); // allocate the entire buffer and check the last address buffer.access (const_cast (last)); tap.expect (!has_fault (last), "last is valid after total commit"); // unmap the buffer and check centre and last are invalid buffer.access (const_cast (first)); tap.expect (!has_fault (first), "first value remains valid after release"); tap.expect ( has_fault (centre), "centre is invalid after release"); tap.expect ( has_fault (last), "last is invalid after release"); #endif return tap.status (); }