mirror of
https://github.com/ioquake/ioq3.git
synced 2024-11-10 07:11:46 +00:00
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:
parent
2d6171f44c
commit
d2b1d124d4
3 changed files with 56 additions and 17 deletions
|
@ -279,9 +279,14 @@ int Huff_Receive (node_t *node, int *ch, byte *fin) {
|
|||
}
|
||||
|
||||
/* Get a symbol */
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset, int maxoffset) {
|
||||
bloc = *offset;
|
||||
while (node && node->symbol == INTERNAL_NODE) {
|
||||
if (bloc >= maxoffset) {
|
||||
*ch = 0;
|
||||
*offset = maxoffset + 1;
|
||||
return;
|
||||
}
|
||||
if (get_bit(fin)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
|
@ -298,11 +303,15 @@ void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
|
|||
}
|
||||
|
||||
/* Send the prefix code for this node */
|
||||
static void send(node_t *node, node_t *child, byte *fout) {
|
||||
static void send(node_t *node, node_t *child, byte *fout, int maxoffset) {
|
||||
if (node->parent) {
|
||||
send(node->parent, node, fout);
|
||||
send(node->parent, node, fout, maxoffset);
|
||||
}
|
||||
if (child) {
|
||||
if (bloc >= maxoffset) {
|
||||
bloc = maxoffset + 1;
|
||||
return;
|
||||
}
|
||||
if (node->right == child) {
|
||||
add_bit(1, fout);
|
||||
} else {
|
||||
|
@ -312,22 +321,22 @@ static void send(node_t *node, node_t *child, byte *fout) {
|
|||
}
|
||||
|
||||
/* Send a symbol */
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout) {
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout, int maxoffset) {
|
||||
int i;
|
||||
if (huff->loc[ch] == NULL) {
|
||||
/* node_t hasn't been transmitted, send a NYT, then the symbol */
|
||||
Huff_transmit(huff, NYT, fout);
|
||||
Huff_transmit(huff, NYT, fout, maxoffset);
|
||||
for (i = 7; i >= 0; i--) {
|
||||
add_bit((char)((ch >> i) & 0x1), fout);
|
||||
}
|
||||
} else {
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
send(huff->loc[ch], NULL, fout, maxoffset);
|
||||
}
|
||||
}
|
||||
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset, int maxoffset) {
|
||||
bloc = *offset;
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
send(huff->loc[ch], NULL, fout, maxoffset);
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
|
@ -413,7 +422,7 @@ void Huff_Compress(msg_t *mbuf, int offset) {
|
|||
|
||||
for (i=0; i<size; i++ ) {
|
||||
ch = buffer[i];
|
||||
Huff_transmit(&huff, ch, seq); /* Transmit symbol */
|
||||
Huff_transmit(&huff, ch, seq, size<<3); /* Transmit symbol */
|
||||
Huff_addRef(&huff, (byte)ch); /* Do update */
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1196,9 +1196,9 @@ void Huff_Decompress(msg_t *buf, int offset);
|
|||
void Huff_Init(huffman_t *huff);
|
||||
void Huff_addRef(huff_t* huff, byte ch);
|
||||
int Huff_Receive (node_t *node, int *ch, byte *fin);
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout);
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset);
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset);
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout, int maxoffset);
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset, int maxoffset);
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset, int maxoffset);
|
||||
void Huff_putBit( int bit, byte *fout, int *offset);
|
||||
int Huff_getBit( byte *fout, int *offset);
|
||||
|
||||
|
|
Loading…
Reference in a new issue