OK, so I've investigated this a little further, and the problem is in the
strbin function, which is called from FBehavior::UnescapeStringTable.
Some of the strings in this PWAD's BEHAVIOR lumps end with a backslash. This causes strbin to treat the following null character not as the string terminator but as part of an escape sequence. As a result, it corrupts the data that follows, which in this case is the next string in the table. If it happens to be the name of a sound, it gets invalidated, and the proper sound no longer plays.
Here's an example consisting of a part of the real data before and after calling strbin. Non-printable characters are represented with the ^ symbol:
Code: Select all
Doors to the hangar can not be operated while hangar doors open!\n\^mdtthcbo^
Doors to the hangar can not be operated while hangar doors open!^^mdttdcbo^o^
Because the indices in the string table do not change, "mdtthcbo" becomes "tthcbo", while the previous string is not affected at all. To fix this, strbin needs to know where the string actually ends (we do know where the next one starts, so we surely do have this information... right?). It is notable that there doesn't seem to be an UnescapeStringTable method in older source archives. Instead, strbin is called directly from the VM code before printing the string to the screen. It is not used anywhere else. Since the data is not modified in-place, the bug does not occur, though it is quite likely that a buffer overflow occurs instead.