diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c index 3f987e2..ed61779 100644 --- a/wiretap/ngsniffer.c +++ b/wiretap/ngsniffer.c @@ -2284,7 +2284,8 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, } bit_mask = 0; /* don't have any bits yet */ - while (1) + /* Process until we've consumed all the input */ + while (pin < pin_end) { /* Shift down the bit mask we use to see whats encoded */ bit_mask = bit_mask >> 1; @@ -2292,20 +2293,30 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, /* If there are no bits left, time to get another 16 bits */ if ( 0 == bit_mask ) { - bit_mask = 0x8000; /* start with the high bit */ - bit_value = pletohs(pin); /* get the next 16 bits */ - pin += 2; /* skip over what we just grabbed */ - if ( pin >= pin_end ) + /* make sure there are at least *three* bytes + * available - the two bytes of the bit value, + * plus one byte after it */ + if ( pin + 2 >= pin_end ) { - *err = WTAP_ERR_UNC_TRUNCATED; /* data was oddly truncated */ + *err = WTAP_ERR_UNC_TRUNCATED; return ( -1 ); } + bit_mask = 0x8000; /* start with the high bit */ + bit_value = pletohs(pin); /* get the next 16 bits */ + pin += 2; /* skip over what we just grabbed */ } /* Use the bits in bit_value to see what's encoded and what is raw data */ if ( !(bit_mask & bit_value) ) { /* bit not set - raw byte we just copy */ + + /* If length would put us past end of output, avoid overflow */ + if ( pout + 1 > pout_end ) + { + *err = WTAP_ERR_UNC_OVERFLOW; + return ( -1 ); + } *(pout++) = *(pin++); } else @@ -2401,6 +2412,13 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, return ( -1 ); } + /* Check if offset would cause us to copy on top of ourselves */ + if ( pout - offset + length > pout ) + { + *err = WTAP_ERR_UNC_BAD_OFFSET; + return ( -1 ); + } + /* Copy the string from previous text to output position, advance output pointer */ memcpy( pout, pout - offset, length ); @@ -2430,6 +2448,12 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, return ( -1 ); } + /* Check if offset would cause us to copy on top of ourselves */ + if ( pout - offset + length > pout ) + { + *err = WTAP_ERR_UNC_BAD_OFFSET; + return ( -1 ); + } /* Copy the string from previous text to output position, advance output pointer */ memcpy( pout, pout - offset, length ); @@ -2437,10 +2461,6 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, break; } } - - /* If we've consumed all the input, we are done */ - if ( pin >= pin_end ) - break; } return (int) ( pout - outbuf ); /* return length of expanded text */