Quasar
Moderator

Posts: 4615
Registered: 08-00 |
esselfortium's Saturn X project suddenly suffered a bizarre setback in the form of a messageless lockup during W_Init.
The fact that there's no message and a lockup is the fault of I_Error, which assumes certain side effects of I_Init have occurred, and I_Init is not called until well after W_InitMultipleFiles (In particular it calls DMX's TSM_DelService with an uninitialized tsm_ID variable).
However, the cause of the crash in the first place is this code, from vanilla's W_AddFile:
code:
v10 = 16 * v41; // v41 == numlumps, read from the directory
v26 = 16 * v41 + 3;
LOWORD(v26) = v26 & 0xFFFC;
if ( v26 >= (unsigned int)alloca_imp_() )
v11 = 0;
else
v11 = &a1;
lseek(v35, v42, 0);
v27 = v11;
v28 = v34;
read(v35, v8, v10);
if ( !v28 )
numlumps += v41;
The bolded portion of the code is an inlined expansion of Watcom's alloca macro.
alloca is a non-standard but widely implemented C function which allocates memory from the temporary variable store, typically implemented on the stack. the "a" in alloca means "automatic", because such allocations have the same lifetime as local or "auto" variables.
However, alloca is limited in Watcom's implementation to the size of the stack segment as determined at compile time. In vanilla Doom, this is a 64 KB segment. This means that, subtracting off the stack space already used when calling W_AddFile, there is only room left for approximately 4046 lumps.
Any wad larger than this will cause memory corruption and/or a lockup, chiefly because the return value of alloca is not checked by the code (note where it stores 0, or NULL, into "v11" if the size being allocated is greater than the return value of alloca_imp, which is a Watcom internal function that returns the amount of stack space available). But, this return value is passed blindly to the read function later.
This means it is reading a file into low DOS memory, starting at offset 0 and continuing for the size of the wad directory. This would trash the entire interrupt table and a considerable portion of whatever follows - right in the middle of a file operation. This is extremely dangerous.
Testing by CSonicGo on a real DOS machine showed bizarre unexplainable behaviors such as randomly changing text displaying in awful colors.
|