Blob Blame History Raw
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 */