I'm trying to do some tests on page fault exception on Windows. The requirement is to put some data into the page boundary so that reading the data will trigger a page fault exception.
Concretely, the test consists of 7 bytes (for example) which are logically consecutive and allocated. I need the first 5 bytes to be located on a physically allocated page, but the next 2 bytes are located on a page which is not yet physically allocated.
So that reading this 7 bytes will trigger a page fault exception, while reading only 4 bytes will not.
I intially think that I should allocate two pages, write 7 byte data over the boundary, and page out the second page.
Can I do this using some user-mode Windows API?
Yes, this is possible in user-land. You'd usually reserve all the pages at once with VirtualAlloc
and then commit part of it. You can change the protection back and forth with VirtualProtect
after committing.
#include <cstdint>
#include <iostream>
#include <Windows.h>
int main()
{
//Retrieve currently configured page-size
SYSTEM_INFO info;
GetSystemInfo(&info);
DWORD pageSize = info.dwPageSize;
//Reserve 2 pages
void *mem = VirtualAlloc(NULL, pageSize*2, MEM_RESERVE, PAGE_NOACCESS);
//Commit first page with read/write premissions
VirtualAlloc(mem, pageSize, MEM_COMMIT, PAGE_READWRITE);
//get pointer with 5 bytes in the first page
uint8_t* ptrAcross = (uint8_t*)mem + pageSize - 5;
//Fill first 5 bytes
FillMemory(ptrAcross, 5, 0x55);
try
{
//Try to fill 6th byte
FillMemory(ptrAcross+5, 1, 0x55);
}
catch(...) // only catches the access violation when compiled with /EHa
{
std::cout << "Access violation" << std::endl;
}
std::cout << "Program finished" <<std::endl;
VirtualFree(mem, 0, MEM_RELEASE);
return 0;
}