diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-09-11 13:29:37 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-09-11 20:30:20 +0000 |
commit | 47c592938ba9f0caeacc4c2ccadb370e72f293a2 (patch) | |
tree | 9964603e3974d2130e467d7cff564a5c7bc25d12 /wiretap/ngsniffer.c | |
parent | ab6ad63e25a9f2e4e8b6e7845dd4513db5232811 (diff) | |
download | wireshark-47c592938ba9f0caeacc4c2ccadb370e72f293a2.tar.gz wireshark-47c592938ba9f0caeacc4c2ccadb370e72f293a2.tar.bz2 wireshark-47c592938ba9f0caeacc4c2ccadb370e72f293a2.zip |
Add some additional checks in SnifferDecompress().
Check the input pointer in the while clause of the loop, so that we
handle an empty input buffer.
When reading a bit mask, check before fetching the bit mask that we have
two bytes of bit mask and the byte after it.
Before putting an uncompressed input byte into the output, make sure we
wouldn't run past the end of the output buffer.
Before copying an earlier string from the output buffer, make sure it
doesn't run past the end of the data we've decompressed so far.
Bug: 10461
Change-Id: I8bb8d0d291368ae8bf0ac26970ff54d3262a7e6e
Reviewed-on: https://code.wireshark.org/review/4083
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'wiretap/ngsniffer.c')
-rw-r--r-- | wiretap/ngsniffer.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c index 99feaa2f59..888ed250fa 100644 --- a/wiretap/ngsniffer.c +++ b/wiretap/ngsniffer.c @@ -2242,7 +2242,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; @@ -2250,20 +2251,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 = pletoh16(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 = pletoh16(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 @@ -2358,6 +2369,12 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, *err = WTAP_ERR_UNC_OVERFLOW; 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 */ @@ -2387,6 +2404,12 @@ SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf, *err = WTAP_ERR_UNC_OVERFLOW; 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 */ @@ -2395,10 +2418,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 */ |