Duke3D: Internal compiler errors may occur if CON script buffer is resized.
When resizing the script buffer, the game runs a check over it whether all the pointers in the apScript
array are valid. This check starts at apScript[0]
and ranges all the way to apScript[g_scriptSize-1]
, i.e. the current maximum defined script size. An internal compiler error occurs anytime one of these pointer checks fails.
Moreover, note that a resize occurs whenever the g_scriptPtr
comes within a range of 4096 bytes of the limit.
As discussed on Discord, there are two different cases where resizing the CON script buffer can lead to an internal compiler error.
- The first occurs with high probability when the script buffer is resized twice in a row. The cause for this is that the
bitptr
array, which indicates which bytecode positions contain pointers, isn't zero'ed out when it is resized. This causes the last few entries corresponding to the 4096 bytes of theapScript
array to contain random garbage data.
As a result, on the second resizing, the check at the start of C_SetScriptSize
is led to believe that the empty entries at the end of the apScript
array are actually pointers. And since the actual values are all 0 (due to the memset
statement), the game will produce a compiler error for each of the locations it thinks is a pointer. This is the cause of the 'Internal Compiler Error' storms some users may have noticed in the past.
- The second instance can occur if the script buffer is resized right after a pointer to
g_scriptPtr
was stored inside theapScript
array. This can occur as part of the parsing of IF statements. During the resize, the check at the start ofC_SetScriptSize()
will eventually come across the entryapScript[i]
that stores this pointer, and perform the following comparison:apScript[i] >= (intptr_t)g_scriptPtr)
This is fulfilled due to equivalence and thus results in a compiler error. I believe this is a false positive however, as storing the pointer to the current g_scriptPtr
inside the array is intended behavior of the If
statements, and the pointer will be relocated properly after the resize. Hence the conditional should be altered to check for strict inequality.