fixed bitstream string parsing not reading the last byte of max length strings ("q3msgboom")

This commit is contained in:
myT 2018-12-08 00:24:51 +01:00
parent 55ae7645b1
commit 2f70685fa3
2 changed files with 40 additions and 57 deletions

View file

@ -16,6 +16,8 @@ add: /toggle can now accept a value sequence (2 or more entries) to loop through
chg: on Windows, the upper limit of open stdio file handles was raised from 512 to 2048 chg: on Windows, the upper limit of open stdio file handles was raised from 512 to 2048
fix: the last byte of a maximum length bitstream string wasn't parsed ("q3msgboom")
fix: aborting demo playback would crash when the "nextdemo" cvar was set to play a demo fix: aborting demo playback would crash when the "nextdemo" cvar was set to play a demo
fix: no longer feeding cs commands that came from a previous gamestate to cgame fix: no longer feeding cs commands that came from a previous gamestate to cgame

View file

@ -336,86 +336,67 @@ int MSG_ReadLong( msg_t *msg )
return c; return c;
} }
//
// Notes about the MSG_Read*String* functions
//
// If N is the string buffer size, then:
// - the max. string length is N-1 because
// the NULL-terminator is part of the buffer
// - the loop can call MSG_ReadByte at most N times
// - the loop can write at most N-1 chars
// to leave space for the NULL terminator
//
// The "q3msgboom" bug was happening because a string
// of length >= N-1 was invoking MSG_ReadByte N-1 times
// instead of N times, leaving the bit stream in an
// invalid state and later leading to the
// "Illegible server message" drop error.
//
char *MSG_ReadString( msg_t *msg ) { char *MSG_ReadString( msg_t *msg ) {
static char string[MAX_STRING_CHARS]; static char string[MAX_STRING_CHARS];
int l,c;
l = 0; int l = 0;
do { for (;;) {
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds const int c = MSG_ReadByte(msg);
if ( c == -1 || c == 0 ) { if (c <= 0 || l >= sizeof(string) - 1)
break; break;
}
// translate all fmt spec to avoid crash bugs
if ( c == '%' ) {
c = '.';
}
// don't allow higher ascii values
if ( c > 127 ) {
c = '.';
}
string[l] = c; string[l++] = c == '%' || c > 127 ? '.' : c;
l++; }
} while (l < sizeof(string)-1); string[l] = '\0';
string[l] = 0;
return string; return string;
} }
char *MSG_ReadBigString( msg_t *msg ) { char *MSG_ReadBigString( msg_t *msg ) {
static char string[BIG_INFO_STRING]; static char string[BIG_INFO_STRING];
int l,c;
l = 0; int l = 0;
do { for (;;) {
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds const int c = MSG_ReadByte(msg);
if ( c == -1 || c == 0 ) { if (c <= 0 || l >= sizeof(string) - 1)
break; break;
}
// translate all fmt spec to avoid crash bugs
if ( c == '%' ) {
c = '.';
}
// don't allow higher ascii values
if ( c > 127 ) {
c = '.';
}
string[l] = c; string[l++] = c == '%' || c > 127 ? '.' : c;
l++; }
} while (l < sizeof(string)-1); string[l] = '\0';
string[l] = 0;
return string; return string;
} }
char *MSG_ReadStringLine( msg_t *msg ) { char *MSG_ReadStringLine( msg_t *msg ) {
static char string[MAX_STRING_CHARS]; static char string[MAX_STRING_CHARS];
int l,c;
l = 0; int l = 0;
do { for (;;) {
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds const int c = MSG_ReadByte(msg);
if (c == -1 || c == 0 || c == '\n') { if (c <= 0 || c == '\n' || l >= sizeof(string) - 1)
break; break;
}
// translate all fmt spec to avoid crash bugs
if ( c == '%' ) {
c = '.';
}
// don't allow higher ascii values
if ( c > 127 ) {
c = '.';
}
string[l] = c; string[l++] = c == '%' || c > 127 ? '.' : c;
l++; }
} while (l < sizeof(string)-1); string[l] = '\0';
string[l] = 0;
return string; return string;
} }