iemejia commented on code in PR #3856:
URL: https://github.com/apache/avro/pull/3856#discussion_r3567424085


##########
lang/php/lib/DataFile/AvroDataIOReader.php:
##########
@@ -276,17 +345,73 @@ private function snappyUncompress(string $compressed): 
string
         if (!extension_loaded('snappy')) {
             throw new AvroException('Please install ext-snappy to use snappy 
compression.');
         }
-        $crc32 = unpack('N', substr((string) $compressed, -4))[1];
-        $datum = snappy_uncompress(substr((string) $compressed, 0, -4));
+        $maxLength = self::maxDecompressLength();
+        // The block is a Snappy payload followed by a 4-byte CRC32 trailer; a
+        // shorter block is malformed and must not be sliced with negative
+        // offsets (which would make unpack() return false below).
+        if (strlen($compressed) < 4) {
+            throw new AvroException('snappy uncompression failed - block too 
small.');
+        }
+        $payload = substr($compressed, 0, -4);
+        $unpacked = unpack('N', substr($compressed, -4));
+        if (false === $unpacked) {
+            throw new AvroException('snappy uncompression failed - missing 
crc32 trailer.');
+        }
+        $crc32 = $unpacked[1];
+        // The Snappy block header declares the uncompressed length as a 
varint;
+        // reject an over-large block before allocating for it. Parsed with an
+        // early cap so it stays correct even if a 32-bit int would overflow.
+        self::ensureSnappyWithinLimit($payload, $maxLength);
+        $datum = snappy_uncompress($payload);
 
         if (false === $datum) {
             throw new AvroException('snappy uncompression failed.');
         }
 
+        self::checkDecompressLength(strlen($datum), $maxLength);
+
         if ($crc32 !== crc32($datum)) {
             throw new AvroException('snappy uncompression failed - crc32 
mismatch.');
         }

Review Comment:
   Fixed — the CRC32 values are now compared via `sprintf('%u', ...)` on both 
sides, so a float from unpack('N') on 32-bit PHP and a (possibly negative) int 
from crc32() normalize to the same unsigned representation instead of a false 
mismatch.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to