Почему после buf = malloc(1) с кучей полной страницы исключение защитной страницы не генерируется до тех пор, пока buf[16] не будет перезаписан?
Код в баге
int main() { void *ptr = 0; int overrun = 1; ptr = malloc(overrun); while(overrun++) { if(!ptr) while(1) Sleep(500); *((char*)ptr + (overrun+1)) = 'a'; printf("\n%d\n",overrun); } return 0; }
Из меню проекта Visual Studio 2010 удостоверился, что сборка - "Release" и "x64" (машина - x64)
Включить FULL PAGE HEAP
gflags /p /enable test.exe /full
Сделать отладчик по умолчанию для windbg
E:\installed\Debugging Tools for Windows (x64)>windbg -I
Запустите код как отдельный exe из
cmd
без отладчикаВыход:
2 3 4 5 6 7 8 9 10 11 12 13 14
после чего видно, что windbg ловит коррупцию. И я думал, что куча полной страницы предполагает мгновенное обнаружение коррупции.
Любые комментарии относительно того, почему куча полной страницы отстой?
2 ответа
Поскольку выделение кучи требуется для выравнивания, переполнение, которое не пересекает границу выравнивания, не может быть обнаружено во время переполнения, поскольку защита памяти является гранулярной, а не байтовой. Это аппаратное ограничение. Переполнение будет обнаружено, когда вы освободите память, и хвостовые байты будут проверены на подделку.
(Кстати, если сказать, что что-то отстой, это снижает вероятность того, что человек, которого вы обвиняете в отстойности, потрудится помочь вам решить вашу проблему.
Чтобы расширить ответ Раймонда. Если вы посмотрите в отладчике исходный указатель, возвращенный через malloc, вы увидите, что это 16 байтов от конца страницы. Это потому, что требование выравнивания HeapAlloc на x64 составляет 16 байтов. Поэтому он поместил запрошенный 1 байт как можно ближе к концу страницы. Как только вы уходите с конца страницы, вы ошибаетесь.