This is an automated email from the git hooks/post-receive script. smcv pushed a commit to tag 1.51b in repository iortcw.
commit 260c39a29af517a08b3ee1a0e78ad654bdd70934 Author: MAN-AT-ARMS <[email protected]> Date: Thu Aug 3 00:06:37 2017 -0400 All: Fix/improve buffer overflow in MSG_ReadBits/MSG_WriteBits --- MP/code/qcommon/huffman.c | 49 ++++++++++++++++++++--------------- MP/code/qcommon/msg.c | 45 +++++++++++++++++++++++++------- MP/code/qcommon/qcommon.h | 6 ++--- SP/code/qcommon/huffman.c | 49 ++++++++++++++++++++--------------- SP/code/qcommon/msg.c | 65 ++++++++++++++++++++++++++++++++++------------- SP/code/qcommon/qcommon.h | 6 ++--- 6 files changed, 145 insertions(+), 75 deletions(-) diff --git a/MP/code/qcommon/huffman.c b/MP/code/qcommon/huffman.c index 00b007e..88b972c 100644 --- a/MP/code/qcommon/huffman.c +++ b/MP/code/qcommon/huffman.c @@ -36,7 +36,7 @@ If you have questions concerning this license or the applicable additional terms static int bloc = 0; -void Huff_putBit( int bit, byte *fout, int *offset ) { +void Huff_putBit( int bit, byte *fout, int *offset ) { bloc = *offset; if ( ( bloc & 7 ) == 0 ) { fout[( bloc >> 3 )] = 0; @@ -46,17 +46,15 @@ void Huff_putBit( int bit, byte *fout, int *offset ) { *offset = bloc; } -int Huff_getBloc(void) -{ +int Huff_getBloc( void ) { return bloc; } -void Huff_setBloc(int _bloc) -{ +void Huff_setBloc( int _bloc ) { bloc = _bloc; } -int Huff_getBit( byte *fin, int *offset ) { +int Huff_getBit( byte *fin, int *offset ) { int t; bloc = *offset; t = ( fin[( bloc >> 3 )] >> ( bloc & 7 ) ) & 0x1; @@ -286,9 +284,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 { @@ -305,11 +308,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 { @@ -319,22 +326,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; } @@ -374,17 +381,17 @@ void Huff_Decompress( msg_t *mbuf, int offset ) { seq[j] = 0; break; } - Huff_Receive( huff.tree, &ch, buffer ); /* Get a character */ - if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */ + Huff_Receive( huff.tree, &ch, buffer ); /* Get a character */ + if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */ ch = 0; for ( i = 0; i < 8; i++ ) { ch = ( ch << 1 ) + get_bit( buffer ); } } - seq[j] = ch; /* Write symbol */ + seq[j] = ch; /* Write symbol */ - Huff_addRef( &huff, (byte)ch ); /* Increment node */ + Huff_addRef( &huff, (byte)ch ); /* Increment node */ } mbuf->cursize = cch + offset; Com_Memcpy( mbuf->data + offset, seq, cch ); @@ -420,11 +427,11 @@ 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_addRef( &huff, (byte)ch ); /* Do update */ + Huff_transmit( &huff, ch, seq, size << 3 ); /* Transmit symbol */ + Huff_addRef( &huff, (byte)ch ); /* Do update */ } - bloc += 8; // next byte + bloc += 8; // next byte mbuf->cursize = ( bloc >> 3 ) + offset; Com_Memcpy( mbuf->data + offset, seq, ( bloc >> 3 ) ); diff --git a/MP/code/qcommon/msg.c b/MP/code/qcommon/msg.c index 56ef5fc..e8a5e7e 100644 --- a/MP/code/qcommon/msg.c +++ b/MP/code/qcommon/msg.c @@ -114,9 +114,7 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) { msg->uncompsize += bits; // NERVE - SMF - net debugging - // this isn't an exact overflow check, but close enough - if ( msg->maxsize - msg->cursize < 4 ) { - msg->overflowed = qtrue; + if ( msg->overflowed ) { return; } @@ -128,6 +126,11 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) { bits = -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; @@ -150,6 +153,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 ); @@ -158,8 +165,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; @@ -173,6 +185,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 ) { @@ -183,6 +199,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]; msg->readcount += 1; @@ -205,6 +226,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 ); } @@ -213,9 +238,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); } @@ -280,8 +310,8 @@ void MSG_WriteLong( msg_t *sb, int c ) { } void MSG_WriteFloat( msg_t *sb, float f ) { - floatint_t dat; + dat.f = f; MSG_WriteBits( sb, dat.i, 32 ); } @@ -409,7 +439,6 @@ int MSG_ReadLong( msg_t *msg ) { } float MSG_ReadFloat( msg_t *msg ) { - floatint_t dat; dat.i = MSG_ReadBits( msg, 32 ); @@ -462,7 +491,6 @@ char *MSG_ReadBigString( msg_t *msg ) { if ( c == '%' ) { c = '.'; } - // don't allow higher ascii values if ( c > 127 ) { c = '.'; @@ -491,7 +519,6 @@ char *MSG_ReadStringLine( msg_t *msg ) { if ( c == '%' ) { c = '.'; } - // don't allow higher ascii values if ( c > 127 ) { c = '.'; diff --git a/MP/code/qcommon/qcommon.h b/MP/code/qcommon/qcommon.h index 14a9fbf..8bc4341 100644 --- a/MP/code/qcommon/qcommon.h +++ b/MP/code/qcommon/qcommon.h @@ -1332,9 +1332,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 ); diff --git a/SP/code/qcommon/huffman.c b/SP/code/qcommon/huffman.c index 00b007e..88b972c 100644 --- a/SP/code/qcommon/huffman.c +++ b/SP/code/qcommon/huffman.c @@ -36,7 +36,7 @@ If you have questions concerning this license or the applicable additional terms static int bloc = 0; -void Huff_putBit( int bit, byte *fout, int *offset ) { +void Huff_putBit( int bit, byte *fout, int *offset ) { bloc = *offset; if ( ( bloc & 7 ) == 0 ) { fout[( bloc >> 3 )] = 0; @@ -46,17 +46,15 @@ void Huff_putBit( int bit, byte *fout, int *offset ) { *offset = bloc; } -int Huff_getBloc(void) -{ +int Huff_getBloc( void ) { return bloc; } -void Huff_setBloc(int _bloc) -{ +void Huff_setBloc( int _bloc ) { bloc = _bloc; } -int Huff_getBit( byte *fin, int *offset ) { +int Huff_getBit( byte *fin, int *offset ) { int t; bloc = *offset; t = ( fin[( bloc >> 3 )] >> ( bloc & 7 ) ) & 0x1; @@ -286,9 +284,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 { @@ -305,11 +308,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 { @@ -319,22 +326,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; } @@ -374,17 +381,17 @@ void Huff_Decompress( msg_t *mbuf, int offset ) { seq[j] = 0; break; } - Huff_Receive( huff.tree, &ch, buffer ); /* Get a character */ - if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */ + Huff_Receive( huff.tree, &ch, buffer ); /* Get a character */ + if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */ ch = 0; for ( i = 0; i < 8; i++ ) { ch = ( ch << 1 ) + get_bit( buffer ); } } - seq[j] = ch; /* Write symbol */ + seq[j] = ch; /* Write symbol */ - Huff_addRef( &huff, (byte)ch ); /* Increment node */ + Huff_addRef( &huff, (byte)ch ); /* Increment node */ } mbuf->cursize = cch + offset; Com_Memcpy( mbuf->data + offset, seq, cch ); @@ -420,11 +427,11 @@ 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_addRef( &huff, (byte)ch ); /* Do update */ + Huff_transmit( &huff, ch, seq, size << 3 ); /* Transmit symbol */ + Huff_addRef( &huff, (byte)ch ); /* Do update */ } - bloc += 8; // next byte + bloc += 8; // next byte mbuf->cursize = ( bloc >> 3 ) + offset; Com_Memcpy( mbuf->data + offset, seq, ( bloc >> 3 ) ); diff --git a/SP/code/qcommon/msg.c b/SP/code/qcommon/msg.c index 350cfd0..f88e88c 100644 --- a/SP/code/qcommon/msg.c +++ b/SP/code/qcommon/msg.c @@ -87,14 +87,13 @@ void MSG_BeginReadingOOB( msg_t *msg ) { msg->oob = qtrue; } -void MSG_Copy(msg_t *buf, byte *data, int length, msg_t *src) -{ - if (length<src->cursize) { - Com_Error( ERR_DROP, "MSG_Copy: can't copy into a smaller msg_t buffer"); +void MSG_Copy( msg_t *buf, byte *data, int length, msg_t *src ) { + if ( length < src->cursize ) { + Com_Error( ERR_DROP, "MSG_Copy: can't copy into a smaller msg_t buffer" ); } - Com_Memcpy(buf, src, sizeof(msg_t)); + Com_Memcpy( buf, src, sizeof( msg_t ) ); buf->data = data; - Com_Memcpy(buf->data, src->data, src->cursize); + Com_Memcpy( buf->data, src->data, src->cursize ); } /* @@ -111,9 +110,8 @@ 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; } @@ -125,13 +123,18 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) { bits = -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; msg->bit += 8; } else if ( bits == 16 ) { short temp = value; - + CopyLittleShort(&msg->data[msg->cursize], &temp); msg->cursize += 2; msg->bit += 16; @@ -147,6 +150,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 ); @@ -155,8 +162,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; @@ -170,6 +182,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 ) { @@ -180,6 +196,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]; msg->readcount += 1; @@ -202,6 +223,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 ); } @@ -210,9 +235,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); } @@ -607,7 +637,7 @@ void MSG_WriteDeltaKey( msg_t *msg, int key, int oldV, int newV, int bits ) { int MSG_ReadDeltaKey( msg_t *msg, int key, int oldV, int bits ) { if ( MSG_ReadBits( msg, 1 ) ) { - return MSG_ReadBits( msg, bits ) ^ ( key & kbitmask[bits - 1] ); + return MSG_ReadBits( msg, bits ) ^ ( key & kbitmask[ bits - 1 ] ); } return oldV; } @@ -643,9 +673,9 @@ usercmd_t communication */ /* -===================== +======================== MSG_WriteDeltaUsercmdKey -===================== +======================== */ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *to ) { if ( to->serverTime - from->serverTime < 256 ) { @@ -690,9 +720,9 @@ void MSG_WriteDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t * /* -===================== +======================= MSG_ReadDeltaUsercmdKey -===================== +======================= */ void MSG_ReadDeltaUsercmdKey( msg_t *msg, int key, usercmd_t *from, usercmd_t *to ) { if ( MSG_ReadBits( msg, 1 ) ) { @@ -896,7 +926,6 @@ void MSG_ReportChangeVectors_f( void ) { #endif } - typedef struct { char *name; int offset; diff --git a/SP/code/qcommon/qcommon.h b/SP/code/qcommon/qcommon.h index 1c556dc..ba6238d 100644 --- a/SP/code/qcommon/qcommon.h +++ b/SP/code/qcommon/qcommon.h @@ -1246,9 +1246,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 ); -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/iortcw.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

