Page MenuHomePhabricator

GIFMetadataExtractor: PHP Warning: unpack(): Type v: not enough input, need 2, have 1
Open, LowPublicPRODUCTION ERROR

Description

Error

MediaWiki version: 1.36.0-wmf.2

message
PHP Warning: unpack(): Type v: not enough input, need 2, have 1

Impact

~10 of these since deploy of 1.36.0-wmf.2.

Noticed while looking at T259592.

Details

Request ID
b525eab7-15c3-44be-a582-184f8b975ed4
Request URL
https://commons.wikimedia.org/w/api.php
Stack Trace
exception.trace
#0 [internal function]: MWExceptionHandler::handleError(integer, string, string, integer, array)
#1 /srv/mediawiki/php-1.36.0-wmf.2/includes/media/GIFMetadataExtractor.php(87): unpack(string, string)
#2 /srv/mediawiki/php-1.36.0-wmf.2/includes/media/BitmapMetadataHandler.php(239): GIFMetadataExtractor::getMetadata(string)
#3 /srv/mediawiki/php-1.36.0-wmf.2/includes/media/GIFHandler.php(37): BitmapMetadataHandler::GIF(string)
#4 /srv/mediawiki/php-1.36.0-wmf.2/includes/filerepo/file/UnregisteredLocalFile.php(193): GIFHandler->getMetadata(UploadStashFile, string)
#5 /srv/mediawiki/php-1.36.0-wmf.2/includes/media/GIFHandler.php(205): UnregisteredLocalFile->getMetadata()
#6 /srv/mediawiki/php-1.36.0-wmf.2/includes/filerepo/file/File.php(612): GIFHandler->getLength(UploadStashFile)
#7 /srv/mediawiki/php-1.36.0-wmf.2/includes/api/ApiQueryImageInfo.php(447): File->getLength()
#8 /srv/mediawiki/php-1.36.0-wmf.2/includes/upload/UploadBase.php(2198): ApiQueryImageInfo::getInfo(UploadStashFile, array, ApiResult)
#9 /srv/mediawiki/php-1.36.0-wmf.2/includes/api/ApiUpload.php(111): UploadBase->getImageInfo(ApiResult)
#10 /srv/mediawiki/php-1.36.0-wmf.2/includes/api/ApiMain.php(1593): ApiUpload->execute()
#11 /srv/mediawiki/php-1.36.0-wmf.2/includes/api/ApiMain.php(529): ApiMain->executeAction()
#12 /srv/mediawiki/php-1.36.0-wmf.2/includes/api/ApiMain.php(500): ApiMain->executeActionWithErrorHandling()
#13 /srv/mediawiki/php-1.36.0-wmf.2/api.php(90): ApiMain->execute()
#14 /srv/mediawiki/php-1.36.0-wmf.2/api.php(45): wfApiMain()
#15 /srv/mediawiki/w/api.php(3): require(string)
#16 {main}

Event Timeline

brennen created this task.Aug 4 2020, 4:02 PM
Restricted Application added a subscriber: Aklapper. · View Herald TranscriptAug 4 2020, 4:02 PM
brennen moved this task from Backlog to Logs/Train on the User-brennen board.
eprodromou added a subscriber: eprodromou.

This seems to be a problem with GIF file handling that is surfacing through the Action API. We're handing off to Structured Data, but feel free to re-tag us if this seems like a Platform issue instead.

Restricted Application added a project: Structured-Data-Backlog. · View Herald TranscriptAug 4 2020, 8:07 PM
TheDJ added a subscriber: TheDJ.Aug 4 2020, 8:53 PM

Its basically saying that it can't read the width/height of the GIF file from the metadata.. Most likely that means the file was incompletely uploaded.

We should probably check the filesize here, to make sure you have at least a complete header in the file, or check fread for not returning FALSE.

MarkTraceur triaged this task as Low priority.Aug 4 2020, 10:01 PM
MarkTraceur added a subscriber: MarkTraceur.

Prioritizing as low for a couple of reasons:

  1. Can't reproduce; API calls for imageinfo on GIFs work fine for me
  2. 10 errors in a week means it's pretty minor, I assume
  3. If this is being tasked to the Structured Data team, we have very little expertise in dealing with low-level media file format handling, so there's a chance we can't handle it as well as $someoneElse

Maybe @TheDJ is right and this is just a simple "oh, it's a corrupted file, throw a more different error" but I'd like more information than we have before proceeding personally.

ApiQueryImageInfo::getInfo(UploadStashFile, array, ApiResult) can indicate a not-finished upload as the file was stashed

But the getImageInfo is only called for "Success" and the even for chunk upload the min size is 1024 (wgMinUploadChunkSize) which is enough for the code reading metadata

The relevant code is:

		// Read width and height.
		$buf = fread( $fh, 2 );
		$width = unpack( 'v', $buf )[1];
		$buf = fread( $fh, 2 );
		$height = unpack( 'v', $buf )[1];

The stack trace includes the types and unpack is not called with false, I would assume that fread is not returning false here, but it seems not returning the requested 2 bytes

GIFHandler is catching Exceptions for broken files (and log them), but not Errors/Throwables.

Without the file it seems hard to follows what happens