Fix/improve buffer overflow in MSG_ReadBits/MSG_WriteBits

Prevent reading past end of message in MSG_ReadBits. If read past
end of msg->data buffer (16348 bytes) the engine could SEGFAULT.
Make MSG_WriteBits use an exact buffer overflow check instead of
possibly failing with a few bytes left.
This commit is contained in:
Zack Middleton 2017-08-02 14:55:10 -05:00
parent 2d6171f44c
commit d2b1d124d4
3 changed files with 56 additions and 17 deletions

View file

@ -107,9 +107,7 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
oldsize += bits;
// this isn't an exact overflow check, but close enough
if ( msg->maxsize - msg->cursize < 4 ) {
msg->overflowed = qtrue;
if ( msg->overflowed ) {
return;
}
@ -122,6 +120,11 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
}
if ( msg->oob ) {
if ( msg->cursize + ( bits >> 3 ) > msg->maxsize ) {
msg->overflowed = qtrue;
return;
}
if ( bits == 8 ) {
msg->data[msg->cursize] = value;
msg->cursize += 1;
@ -144,6 +147,10 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
if ( bits&7 ) {
int nbits;
nbits = bits&7;
if ( msg->bit + nbits > msg->maxsize << 3 ) {
msg->overflowed = qtrue;
return;
}
for( i = 0; i < nbits; i++ ) {
Huff_putBit( (value & 1), msg->data, &msg->bit );
value = (value >> 1);
@ -152,8 +159,13 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
}
if ( bits ) {
for( i = 0; i < bits; i += 8 ) {
Huff_offsetTransmit( &msgHuff.compressor, (value & 0xff), msg->data, &msg->bit );
Huff_offsetTransmit( &msgHuff.compressor, (value & 0xff), msg->data, &msg->bit, msg->maxsize << 3 );
value = (value >> 8);
if ( msg->bit > msg->maxsize << 3 ) {
msg->overflowed = qtrue;
return;
}
}
}
msg->cursize = (msg->bit >> 3) + 1;
@ -167,6 +179,10 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
int i, nbits;
// FILE* fp;
if ( msg->readcount > msg->cursize ) {
return 0;
}
value = 0;
if ( bits < 0 ) {
@ -177,6 +193,11 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
}
if (msg->oob) {
if (msg->readcount + (bits>>3) > msg->cursize) {
msg->readcount = msg->cursize + 1;
return 0;
}
if(bits==8)
{
value = msg->data[msg->readcount];
@ -204,6 +225,10 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
nbits = 0;
if (bits&7) {
nbits = bits&7;
if (msg->bit + nbits > msg->cursize << 3) {
msg->readcount = msg->cursize + 1;
return 0;
}
for(i=0;i<nbits;i++) {
value |= (Huff_getBit(msg->data, &msg->bit)<<i);
}
@ -212,9 +237,14 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
if (bits) {
// fp = fopen("c:\\netchan.bin", "a");
for(i=0;i<bits;i+=8) {
Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit);
Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit, msg->cursize<<3);
// fwrite(&get, 1, 1, fp);
value |= (get<<(i+nbits));
if (msg->bit > msg->cursize<<3) {
msg->readcount = msg->cursize + 1;
return 0;
}
}
// fclose(fp);
}