Skip to content

Commit 8a5bc47

Browse files
authored
Merge pull request #38364 from joshtrichards/jr-preview-libgd-webp-animation-bypass
2 parents 4642d82 + 046fe8d commit 8a5bc47

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

lib/private/legacy/OC_Image.php

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,9 +691,56 @@ public function loadFromFile($imagePath = false) {
691691
if (!$this->checkImageSize($imagePath)) {
692692
return false;
693693
}
694-
$this->resource = @imagecreatefromwebp($imagePath);
694+
695+
// Check for animated header before generating preview since libgd does not handle them well
696+
// Adapted from here: https://stackoverflow.com/a/68491679/4085517 (stripped to only to check for animations + added additional error checking)
697+
// Header format details here: https://developers.google.com/speed/webp/docs/riff_container
698+
699+
// Load up the header data, if any
700+
$fp = fopen($imagePath, 'rb');
701+
if (!$fp) {
702+
return false;
703+
}
704+
$data = fread($fp, 90);
705+
if (!$data) {
706+
return false;
707+
}
708+
fclose($fp);
709+
unset($fp);
710+
711+
$headerFormat = 'A4Riff/' . // get n string
712+
'I1Filesize/' . // get integer (file size but not actual size)
713+
'A4Webp/' . // get n string
714+
'A4Vp/' . // get n string
715+
'A74Chunk';
716+
717+
$header = unpack($headerFormat, $data);
718+
unset($data, $headerFormat);
719+
if (!$header) {
720+
return false;
721+
}
722+
723+
// Check if we're really dealing with a valid WEBP header rather than just one suffixed ".webp"
724+
if (!isset($header['Riff']) || strtoupper($header['Riff']) !== 'RIFF') {
725+
return false;
726+
}
727+
if (!isset($header['Webp']) || strtoupper($header['Webp']) !== 'WEBP') {
728+
return false;
729+
}
730+
if (!isset($header['Vp']) || strpos(strtoupper($header['Vp']), 'VP8') === false) {
731+
return false;
732+
}
733+
734+
// Check for animation indicators
735+
if (strpos(strtoupper($header['Chunk']), 'ANIM') !== false || strpos(strtoupper($header['Chunk']), 'ANMF') !== false) {
736+
// Animated so don't let it reach libgd
737+
$this->logger->debug('OC_Image->loadFromFile, animated WEBP images not supported: ' . $imagePath, ['app' => 'core']);
738+
} else {
739+
// We're safe so give it to libgd
740+
$this->resource = @imagecreatefromwebp($imagePath);
741+
}
695742
} else {
696-
$this->logger->debug('OC_Image->loadFromFile, webp images not supported: ' . $imagePath, ['app' => 'core']);
743+
$this->logger->debug('OC_Image->loadFromFile, WEBP images not supported: ' . $imagePath, ['app' => 'core']);
697744
}
698745
break;
699746
/*

0 commit comments

Comments
 (0)