Изначальная тема:
http://blablabla.xakep.ru/m_2396461/tm.htm
Вот сорец:
http://dl.dropbox.com/u/22509984/EpicFail.cpp (4 кб)
#define INVALID_HANDLE 0xFFFFFFFF
#define RES_HANDLE_BASE 0x80000000
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct ResTable
{
bool Lock;
bool Align;
byte InitSize;
DWORD Size;
DWORD Offset;
int MHandle;
} ResTable[100];
DWORD TablePos, ResCount, TableSize, RandSeed = 1;
byte *Table;
unsigned int Random(DWORD seed)
{
RandSeed = 134775813 * RandSeed + 1;
return (DWORD)RandSeed * (long long)seed >> 32;
}
DWORD AlignValue(DWORD Value, DWORD Alignment)
{
return (Value % Alignment != 0) ? Value += Alignment - (Value % Alignment) : Value;
}
void foo(DWORD Value, DWORD Size)
{
byte Reserved;
if(TablePos + Size > TableSize)
{
TableSize *= 2;
Table = (byte*) realloc(Table, TableSize);
}
switch(Size)
{
case 1: {
Table[TablePos] = Value;
TablePos += Size;
return;
}
case 2: {
*(PWORD) &Table[TablePos] = Value;
TablePos += Size;
return;
}
case 3: {
Reserved = Table[TablePos+4];
*(PDWORD) &Table[TablePos] = Value;
Table[TablePos+3] = Reserved;
TablePos += Size;
return;
}
case 4: {
*(PDWORD) &Table[TablePos] = Value;
TablePos += Size;
return;
}
default: printf("bad input size!\n"); getchar();
}
}
DWORD MemoryAlloc(DWORD Size)
{
DWORD i;
/* Сначало пытаемся найти место в свободных ячейках выше, если нет то выделяем новую */
for(i=0;i<ResCount;i++) if(ResTable[i].Lock == false)
{
if(ResTable[i].InitSize + Size <= 4 && Size != 2)
{
ResTable[ResCount].Offset = ResTable[i].Offset + ResTable[i].InitSize;
ResTable[ResCount].Size = Size;
ResTable[ResCount].Lock = true;
ResTable[ResCount].MHandle = i;
ResTable[ResCount].Align = false;
ResTable[i].Align = false;
ResTable[i].InitSize += Size;
return RES_HANDLE_BASE + ResCount++;
}
}
{
ResTable[ResCount].Size = Size;
ResTable[ResCount].MHandle = -1;
ResTable[ResCount].Offset = ~Size;
switch(Size) {
case 1: ResTable[ResCount].Offset -= 2;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 1;
break;
case 2: ResTable[ResCount].Offset -= 1;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 4;
break;
case 4: ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = false;
ResTable[ResCount].InitSize = 4;
break;
default: ResTable[ResCount].Offset += 1;
ResTable[ResCount].Align = true;
ResTable[ResCount].InitSize = 4;
break;
}
for(i=0;i<ResCount;i++) if(ResTable[i].MHandle == -1) ResTable[ResCount].Offset -= AlignValue(ResTable[i].Size, 4);
return RES_HANDLE_BASE + ResCount++;
}
return INVALID_HANDLE;
}
DWORD LocalVarAddr(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Offset;
}
DWORD LocalVarSize(DWORD Handle)
{
return ResTable[Handle - RES_HANDLE_BASE].Size;
}
void FailFunc(DWORD Handle, BYTE V2)
{
DWORD Offset, Size;
if(Handle >= RES_HANDLE_BASE)
{
Offset = LocalVarAddr(Handle);
Size = LocalVarSize(Handle);
if(~Offset < 0x80)
{
switch(Size)
{
case 1: foo(0,3); break;
case 2: foo(0,4); break;
case 4: foo(0,3); break;
default:printf("Size = %d\nFail found #1\n", Size); getchar();
}
foo(Offset,1);
}
else
{
switch(Size)
{
case 1: foo(0,2); break;
case 2: foo(0,3); break;
case 4: foo(0,2); break;
default:printf("Size = %d\nFail found #2\n", Size); getchar();
}
foo(Offset,4);
}
}
else
{
printf("Debug test\n");
}
}
int main(int argc, char *argv[])
{
RandSeed = 0xC0DEC0DE;
TablePos = 0;
TableSize = 0x100000; // 1MB
Table = (byte*) calloc(TableSize, 1);
FailFunc(MemoryAlloc(1), 0);
return 0;
}
Visual Studio 2010 Express
Флаги компиляции (стандартные, изменены только оптимизация по размеру кода и все):
/Zi /nologo /W3 /WX- /MP /O1 /Oi /Os /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /GF /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Release\EpicFail.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue
Вывод программы:
Size = 1
Fail found #1
дизасм:
[image]
http://dl.dropbox.com/u/22509984/epic.PNG[/image]