Skip to content

Commit

Permalink
Simplify the bit check and improve the JPG validation
Browse files Browse the repository at this point in the history
The previous check was ported from the JS ExifUtil and is meant as a safety check.

An earlier version used a slightly different JPEG (that included a JFIF tag) but was replaced to some 30 bytes with this version.

This also means that any changes to the encoded image could break the following logic thus we convert it into `assert()` to fail hard if adjusted improperly.
  • Loading branch information
dtdesign committed Jan 18, 2025
1 parent 8dafdb1 commit 3eb3c94
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions wcfsetup/install/files/lib/system/image/WebPDecoder.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static function extractExifData(string $filename): array

// Check if the EXIF bit is set.
$flags = \ord(\substr($data, 20, 1));
$hasExif = ((1 << (8 - 5)) & $flags) > 0;
$hasExif = $flags & 0b00001000;
if (!$hasExif) {
return [];
}
Expand Down Expand Up @@ -77,11 +77,16 @@ public static function extractExifData(string $filename): array
// See https://github.com/mathiasbynens/small/blob/267b39f682598eebb0dafe7590b1504be79b5cad/jpeg.jpg
$jpg1x1px = \hex2bin("ffd8ffdb004300030202020202030202020303030304060404040404080606050609080a0a090809090a0c0f0c0a0b0e0b09090d110d0e0f101011100a0c12131210130f101010ffc9000b080001000101011100ffcc000600101005ffda0008010100003f00d2cf20ffd9");

// The image does not have a JFIF tag and instead directly starts with
// the quantization table (DQT, 0xFF xDB) after the start of image (SOI,
// 0xFF 0xD8).
//
// This means our offset is always 2. We could further optimize this by
// ommitting the SOI from the hex string but the \substr() is already
// quite cheap that it doesn't make sense to obscure the image further.
\assert($jpg1x1px[0] === "\xFF" && $jpg1x1px[1] === "\xD8");
\assert($jpg1x1px[2] === "\xFF" && $jpg1x1px[3] === "\xDB");
$offset = 2;
// Check if the second tag is the JFIF tag.
if ($jpg1x1px[2] === 0xff && $jpg1x1px[3] === 0xe0) {
$offset += 2 + (($jpg1x1px[4] << 8) | $jpg1x1px[5]);
}

// Add the markers for the EXIF sequence in JPEGs.
$exifData = "\xFF\xE1\xC3\xEF\x45\x78\x69\x66\x00\x00" . $exifData;
Expand Down

0 comments on commit 3eb3c94

Please sign in to comment.