Page MenuHomePhabricator

"PHP Notice: Undefined offset: 1" / "DivisionByZeroError: Division by zero" when uploading file and parsing GPS EXIF data
Closed, ResolvedPublicPRODUCTION ERROR

Description

These two stacktrace appear paired, not sure in which order:

Error
normalized_message
[{reqId}] {exception_url}   PHP Notice: Undefined offset: 1
FrameLocationCall
from/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(651)
#0/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(651)MWExceptionHandler::handleError(int, string, string, int, array)
#1/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(481)Exif->exifGPStoNumber(string)
#2/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(429)Exif->collapseData()
#3/srv/mediawiki/php-1.44.0-wmf.16/includes/media/BitmapMetadataHandler.php(98)Exif->__construct(string, string)
#4/srv/mediawiki/php-1.44.0-wmf.16/includes/media/BitmapMetadataHandler.php(197)BitmapMetadataHandler->getExif(string, string)
#5/srv/mediawiki/php-1.44.0-wmf.16/includes/media/JpegHandler.php(106)BitmapMetadataHandler::Jpeg(string)
#6/srv/mediawiki/php-1.44.0-wmf.16/includes/media/MediaHandler.php(228)JpegHandler->getSizeAndMetadata(TrivialMediaHandlerState, string)
#7/srv/mediawiki/php-1.44.0-wmf.16/includes/utils/MWFileProps.php(90)MediaHandler->getSizeAndMetadataWithFallback(Wikimedia\FileBackend\FSFile\FSFile, string)
#8/srv/mediawiki/php-1.44.0-wmf.16/includes/upload/UploadBase.php(585)MWFileProps->getPropsFromPath(string, string)
#9/srv/mediawiki/php-1.44.0-wmf.16/includes/upload/UploadBase.php(510)UploadBase->verifyPartialFile()
#10/srv/mediawiki/php-1.44.0-wmf.16/includes/upload/UploadBase.php(433)UploadBase->verifyFile()
#11/srv/mediawiki/php-1.44.0-wmf.16/includes/upload/UploadFromFile.php(99)UploadBase->verifyUpload()
#12/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiUpload.php(822)UploadFromFile->verifyUpload()
#13/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiUpload.php(158)MediaWiki\Api\ApiUpload->verifyUpload()
#14/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(2011)MediaWiki\Api\ApiUpload->execute()
#15/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(946)MediaWiki\Api\ApiMain->executeAction()
#16/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(917)MediaWiki\Api\ApiMain->executeActionWithErrorHandling()
#17/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiEntryPoint.php(152)MediaWiki\Api\ApiMain->execute()
#18/srv/mediawiki/php-1.44.0-wmf.16/includes/MediaWikiEntryPoint.php(202)MediaWiki\Api\ApiEntryPoint->execute()
#19/srv/mediawiki/php-1.44.0-wmf.16/api.php(44)MediaWiki\MediaWikiEntryPoint->run()
#20/srv/mediawiki/w/api.php(3)require(string)
#21{main}
labels.normalized_message
[{reqId}] {exception_url}   PHP Warning: Division by zero
FrameLocationCall
from/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(656)
#0/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(656)MWExceptionHandler::handleError(int, string, string, int, array)
#1/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(483)Exif->exifGPStoNumber(string)
#2/srv/mediawiki/php-1.44.0-wmf.16/includes/media/Exif.php(429)Exif->collapseData()
#3/srv/mediawiki/php-1.44.0-wmf.16/includes/media/BitmapMetadataHandler.php(98)Exif->__construct(string, string)
#4/srv/mediawiki/php-1.44.0-wmf.16/includes/media/BitmapMetadataHandler.php(197)BitmapMetadataHandler->getExif(string, string)
#5/srv/mediawiki/php-1.44.0-wmf.16/includes/media/JpegHandler.php(106)BitmapMetadataHandler::Jpeg(string)
#6/srv/mediawiki/php-1.44.0-wmf.16/includes/media/MediaHandler.php(228)JpegHandler->getSizeAndMetadata(UploadStashFile, string)
#7/srv/mediawiki/php-1.44.0-wmf.16/includes/filerepo/file/UnregisteredLocalFile.php(203)MediaHandler->getSizeAndMetadataWithFallback(UploadStashFile, string)
#8/srv/mediawiki/php-1.44.0-wmf.16/includes/filerepo/file/UnregisteredLocalFile.php(128)UnregisteredLocalFile->getSizeAndMetadata()
#9/srv/mediawiki/php-1.44.0-wmf.16/includes/filerepo/file/UnregisteredLocalFile.php(144)UnregisteredLocalFile->cachePageDimensions(int)
#10/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiQueryImageInfo.php(502)UnregisteredLocalFile->getWidth()
#11/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiUpload.php(227)MediaWiki\Api\ApiQueryImageInfo::getInfo(UploadStashFile, array, MediaWiki\Api\ApiResult)
#12/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiUpload.php(182)MediaWiki\Api\ApiUpload->getUploadImageInfo(UploadFromFile)
#13/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(2011)MediaWiki\Api\ApiUpload->execute()
#14/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(946)MediaWiki\Api\ApiMain->executeAction()
#15/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiMain.php(917)MediaWiki\Api\ApiMain->executeActionWithErrorHandling()
#16/srv/mediawiki/php-1.44.0-wmf.16/includes/api/ApiEntryPoint.php(152)MediaWiki\Api\ApiMain->execute()
#17/srv/mediawiki/php-1.44.0-wmf.16/includes/MediaWikiEntryPoint.php(202)MediaWiki\Api\ApiEntryPoint->execute()
#18/srv/mediawiki/php-1.44.0-wmf.16/api.php(44)MediaWiki\MediaWikiEntryPoint->run()
#19/srv/mediawiki/w/api.php(3)require(string)
#20{main}
Impact

72 occurrences in last 30 minutes (might be all the same uploader but not sure).

Notes
  • No recent changes in the last weeks to Exif.php, BitmapMetadataHandler.php, JpegHandler.php, or MediaHandler.php.
  • Referrer URI is Special:UploadWizard, looks like badly broken GPS data embedded in a file to be uploaded?

Event Timeline

Aklapper renamed this task from "PHP Warning: Division by zero" when uploading file and parsing GPS EXIF data to "PHP Notice: Undefined offset: 1" / "PHP Warning: Division by zero" when uploading file and parsing GPS EXIF data.Feb 12 2025, 2:48 PM
Aklapper updated the task description. (Show Details)

Could be related to T303784: InvalidArgumentException: Cannot add non-finite floats to ApiResult, I think? (I saw a “Cannot add non-finite floats to ApiResult” in logspam-watch earlier, and that task sounds like it’s also related to exif metadata.)

Error
normalized_message
[{reqId}] {exception_url}   PHP Notice: Undefined offset: 1
FrameLocationCall
from/srv/mediawiki/php-1.44.0-wmf.18/includes/media/Exif.php(655)
#0/srv/mediawiki/php-1.44.0-wmf.18/includes/media/Exif.php(655)MWExceptionHandler::handleError(int, string, string, int, array)
#1/srv/mediawiki/php-1.44.0-wmf.18/includes/media/Exif.php(483)Exif->exifGPStoNumber(string)
#2/srv/mediawiki/php-1.44.0-wmf.18/includes/media/Exif.php(429)Exif->collapseData()
#3/srv/mediawiki/php-1.44.0-wmf.18/includes/media/BitmapMetadataHandler.php(98)Exif->__construct(string, string)
#4/srv/mediawiki/php-1.44.0-wmf.18/includes/media/BitmapMetadataHandler.php(197)BitmapMetadataHandler->getExif(string, string)
#5/srv/mediawiki/php-1.44.0-wmf.18/includes/media/JpegHandler.php(106)BitmapMetadataHandler::Jpeg(string)
#6/srv/mediawiki/php-1.44.0-wmf.18/includes/media/MediaHandler.php(228)JpegHandler->getSizeAndMetadata(UploadStashFile, string)
#7/srv/mediawiki/php-1.44.0-wmf.18/includes/filerepo/file/UnregisteredLocalFile.php(203)MediaHandler->getSizeAndMetadataWithFallback(UploadStashFile, string)
#8/srv/mediawiki/php-1.44.0-wmf.18/includes/filerepo/file/UnregisteredLocalFile.php(128)UnregisteredLocalFile->getSizeAndMetadata()
#9/srv/mediawiki/php-1.44.0-wmf.18/includes/filerepo/file/UnregisteredLocalFile.php(144)UnregisteredLocalFile->cachePageDimensions(int)
#10/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiQueryImageInfo.php(502)UnregisteredLocalFile->getWidth()
#11/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiUpload.php(227)MediaWiki\Api\ApiQueryImageInfo::getInfo(UploadStashFile, array, MediaWiki\Api\ApiResult)
#12/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiUpload.php(182)MediaWiki\Api\ApiUpload->getUploadImageInfo(UploadFromFile)
#13/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiMain.php(2012)MediaWiki\Api\ApiUpload->execute()
#14/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiMain.php(947)MediaWiki\Api\ApiMain->executeAction()
#15/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiMain.php(918)MediaWiki\Api\ApiMain->executeActionWithErrorHandling()
#16/srv/mediawiki/php-1.44.0-wmf.18/includes/api/ApiEntryPoint.php(152)MediaWiki\Api\ApiMain->execute()
#17/srv/mediawiki/php-1.44.0-wmf.18/includes/MediaWikiEntryPoint.php(202)MediaWiki\Api\ApiEntryPoint->execute()
#18/srv/mediawiki/php-1.44.0-wmf.18/api.php(44)MediaWiki\MediaWikiEntryPoint->run()
#19/srv/mediawiki/w/api.php(3)require(string)
#20{main}
Impact
Notes

It will depend on the file being uploaded.

Aklapper renamed this task from "PHP Notice: Undefined offset: 1" / "PHP Warning: Division by zero" when uploading file and parsing GPS EXIF data to "PHP Notice: Undefined offset: 1" / "DivisionByZeroError: Division by zero" when uploading file and parsing GPS EXIF data.May 20 2025, 7:13 AM

Still seen in 1.45.0-wmf.1

Hi I'm here to report the same issue. A user of WikiClientLibrary has opened CXuesong/WikiClientLibrary#120 with an image whose EXIF data will definitely trigger the DivisionByZeroError when getting uploaded. I've just tried this image on wikipedia:test:Special:Upload and I got the following exception stack trace

[6f2606b3-56d0-4e57-a90f-0e2e5bbcf0de] /wiki/Special:Upload DivisionByZeroError: Division by zero

Backtrace:

from /srv/mediawiki/php-1.45.0-wmf.11/includes/media/Exif.php(652)
#0 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/Exif.php(481): Exif->exifGPStoNumber(string)
#1 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/Exif.php(429): Exif->collapseData()
#2 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/BitmapMetadataHandler.php(98): Exif->__construct(string, string)
#3 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/BitmapMetadataHandler.php(197): BitmapMetadataHandler->getExif(string, string)
#4 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/JpegHandler.php(107): BitmapMetadataHandler::Jpeg(string)
#5 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/MediaHandler.php(230): JpegHandler->getSizeAndMetadata(TrivialMediaHandlerState, string)
#6 /srv/mediawiki/php-1.45.0-wmf.11/includes/utils/MWFileProps.php(91): MediaHandler->getSizeAndMetadataWithFallback(Wikimedia\FileBackend\FSFile\FSFile, string)
#7 /srv/mediawiki/php-1.45.0-wmf.11/includes/upload/UploadBase.php(589): MWFileProps->getPropsFromPath(string, string)
#8 /srv/mediawiki/php-1.45.0-wmf.11/includes/upload/UploadBase.php(514): UploadBase->verifyPartialFile()
#9 /srv/mediawiki/php-1.45.0-wmf.11/includes/upload/UploadBase.php(437): UploadBase->verifyFile()
#10 /srv/mediawiki/php-1.45.0-wmf.11/includes/upload/UploadFromFile.php(99): UploadBase->verifyUpload()
#11 /srv/mediawiki/php-1.45.0-wmf.11/includes/specials/SpecialUpload.php(755): UploadFromFile->verifyUpload()
#12 /srv/mediawiki/php-1.45.0-wmf.11/includes/specials/SpecialUpload.php(829): MediaWiki\Specials\SpecialUpload->performUploadChecks(MediaWiki\Status\Status)
#13 /srv/mediawiki/php-1.45.0-wmf.11/includes/specials/SpecialUpload.php(297): MediaWiki\Specials\SpecialUpload->processUpload()
#14 /srv/mediawiki/php-1.45.0-wmf.11/includes/specialpage/SpecialPage.php(725): MediaWiki\Specials\SpecialUpload->execute(null)
#15 /srv/mediawiki/php-1.45.0-wmf.11/includes/specialpage/SpecialPageFactory.php(1724): MediaWiki\SpecialPage\SpecialPage->run(null)
#16 /srv/mediawiki/php-1.45.0-wmf.11/includes/actions/ActionEntryPoint.php(499): MediaWiki\SpecialPage\SpecialPageFactory->executePath(string, MediaWiki\Context\RequestContext)
#17 /srv/mediawiki/php-1.45.0-wmf.11/includes/actions/ActionEntryPoint.php(143): MediaWiki\Actions\ActionEntryPoint->performRequest()
#18 /srv/mediawiki/php-1.45.0-wmf.11/includes/MediaWikiEntryPoint.php(198): MediaWiki\Actions\ActionEntryPoint->execute()
#19 /srv/mediawiki/php-1.45.0-wmf.11/index.php(58): MediaWiki\MediaWikiEntryPoint->run()
#20 /srv/mediawiki/w/index.php(3): require(string)
#21 {main}

Hope the information would be helpful for the troubleshooting.

Links to the images in this case... https://github.com/CXuesong/WikiClientLibrary/issues/120#issuecomment-3070786152

466176539-5b06032d-1613-47f7-828f-b74562ce0498.JPG (901×507 px, 98 KB)

ExifTool Version Number         : 13.30
File Name                       : 466176539-5b06032d-1613-47f7-828f-b74562ce0498.JPG
Directory                       : .
File Size                       : 101 kB
File Modification Date/Time     : 2025:07:24 10:04:07+01:00
File Access Date/Time           : 2025:07:24 10:04:09+01:00
File Inode Change Date/Time     : 2025:07:24 10:04:07+01:00
File Permissions                : -rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
Exif Byte Order                 : Little-endian (Intel, II)
Make                            : Xiaomi
Camera Model Name               : 2306EPN60G
Exposure Time                   : 1/2496
F Number                        : 1.9
Exposure Program                : Program AE
ISO                             : 51
Exif Version                    : 0220
Create Date                     : 2025:07:13 10:35:38
Shutter Speed Value             : 1/2495
Aperture Value                  : 1.9
Brightness Value                : 10.3
Exposure Compensation           : 0
Max Aperture Value              : 1.9
Metering Mode                   : Center-weighted average
Flash                           : No Flash
Focal Length                    : 6.9 mm
White Balance                   : Auto
Digital Zoom Ratio              : 1
Focal Length In 35mm Format     : 24 mm
GPS Latitude Ref                : North
GPS Longitude Ref               : East
JFIF Version                    : 1.01
Resolution Unit                 : None
X Resolution                    : 1
Y Resolution                    : 1
Profile CMM Type                : 
Profile Version                 : 4.3.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 2016:01:01 00:00:00
Profile File Signature          : acsp
Primary Platform                : Unknown ()
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : 
Device Model                    : 
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Media-Relative Colorimetric
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : 
Profile ID                      : 0
Profile Description             : sRGB
Red Matrix Column               : 0.43607 0.22249 0.01392
Green Matrix Column             : 0.38515 0.71687 0.09708
Blue Matrix Column              : 0.14307 0.06061 0.7141
Media White Point               : 0.9642 1 0.82491
Red Tone Reproduction Curve     : (Binary data 40 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 40 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 40 bytes, use -b option to extract)
Profile Copyright               : Google Inc. 2016
Image Width                     : 901
Image Height                    : 507
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Aperture                        : 1.9
Image Size                      : 901x507
Megapixels                      : 0.457
Scale Factor To 35 mm Equivalent: 3.5
Shutter Speed                   : 1/2496
GPS Latitude                    : 32 deg 1' 25.88" N
GPS Longitude                   : 34 deg 56' 58.04" E
Circle Of Confusion             : 0.009 mm
Field Of View                   : 73.7 deg
Focal Length                    : 6.9 mm (35 mm equivalent: 24.0 mm)
GPS Position                    : 32 deg 1' 25.88" N, 34 deg 56' 58.04" E
Hyperfocal Distance             : 2.91 m
Light Value                     : 14.1

#0 /srv/mediawiki/php-1.45.0-wmf.11/includes/media/Exif.php(481): Exif->exifGPStoNumber(string) is $this->exifGPStoNumber( 'GPSLatitude' );

Filtered exif list

GPS Latitude Ref                : North
GPS Longitude Ref               : East
GPS Latitude                    : 32 deg 1' 25.88" N
GPS Longitude                   : 34 deg 56' 58.04" E
GPS Position                    : 32 deg 1' 25.88" N, 34 deg 56' 58.04" E

And then

	private function exifGPStoNumber( $prop ) {
		$loc = $this->mFilteredExifData[$prop] ?? null;
		$dir = $this->mFilteredExifData[$prop . 'Ref'] ?? null;
		$res = false;

		if ( $loc !== null && ( $dir === 'N' || $dir === 'S' || $dir === 'E' || $dir === 'W' ) ) {
			[ $num, $denom ] = explode( '/', $loc[0], 2 );
			$res = (int)$num / (int)$denom;
			[ $num, $denom ] = explode( '/', $loc[1], 2 );
			$res += ( (int)$num / (int)$denom ) * ( 1 / 60 );
			[ $num, $denom ] = explode( '/', $loc[2], 2 );
			$res += ( (int)$num / (int)$denom ) * ( 1 / 3600 );

			if ( $dir === 'S' || $dir === 'W' ) {
				// make negative
				$res *= -1;
			}
		}

var_dump( $prop, $loc, $dir ); gives us...

string(11) "GPSLatitude"
string(19) "2909560114/90856023"
string(1) "N"

The relevant (and specifically untested) code has been around since rMW74f16767e771: Merge to trunk everything in img_metadata branch....

Testing another file (exif-gps.jpg included for tests)

GPS Version ID                  : 2.2.0.0
GPS Latitude Ref                : North
GPS Longitude Ref               : West
GPS Altitude Ref                : Below Sea Level
GPS Dilution Of Precision       : 5
GPS Altitude                    : 3.1 m Below Sea Level
GPS Latitude                    : 88 deg 31' 5.00" N
GPS Longitude                   : 21 deg 7' 24.85" W
GPS Position                    : 88 deg 31' 5.00" N, 21 deg 7' 24.85" W

results in...

string(11) "GPSLatitude"
array(3) {
  [0]=>
  string(4) "88/1"
  [1]=>
  string(4) "31/1"
  [2]=>
  string(3) "5/1"
}
string(1) "N"
string(15) "GPSDestLatitude"
NULL
NULL
string(12) "GPSLongitude"
array(3) {
  [0]=>
  string(4) "21/1"
  [1]=>
  string(3) "7/1"
  [2]=>
  string(8) "6213/250"
}
string(1) "W"
string(16) "GPSDestLongitude"
NULL
NULL
string(11) "GPSLatitude"
array(3) {
  [0]=>
  string(4) "88/1"
  [1]=>
  string(4) "31/1"
  [2]=>
  string(3) "5/1"
}
string(1) "N"
string(15) "GPSDestLatitude"
NULL
NULL
string(12) "GPSLongitude"
array(3) {
  [0]=>
  string(4) "21/1"
  [1]=>
  string(3) "7/1"
  [2]=>
  string(8) "6213/250"
}
string(1) "W"
string(16) "GPSDestLongitude"
NULL

So something in MW is failing to reformat that GPS data...

Change #1172270 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/core@master] WIP: Add test for file that fails in Exif::exifGPStoNumber()

https://gerrit.wikimedia.org/r/1172270

Also the hint from https://github.com/CXuesong/WikiClientLibrary/issues/120#issuecomment-3109085653

The user who uploaded the image and reported the bug in my end told me he used Google photos to crop the image before uploading,

var_dump( exif_read_data( "/Users/reedy/Downloads/466176539-5b06032d-1613-47f7-828f-b74562ce0498.JPG", '', true ) );

var_dump( exif_read_data( "/Users/reedy/Downloads/exif-gps.jpg", '', true ) );

exif_read_data seems to extract the GPS data differently, but not sure if that's correct, and MW is at fault for not handling this, or if it's actually an Upstream bug...

https://php.net/manual/en/function.exif-read-data.php

reedy@Sams-Mac-mini mediawiki % php Exif.php
array(5) {
  ["FILE"]=>
  array(6) {
    ["FileName"]=>
    string(50) "466176539-5b06032d-1613-47f7-828f-b74562ce0498.JPG"
    ["FileDateTime"]=>
    int(1753347847)
    ["FileSize"]=>
    int(101143)
    ["FileType"]=>
    int(2)
    ["MimeType"]=>
    string(10) "image/jpeg"
    ["SectionsFound"]=>
    string(24) "ANY_TAG, IFD0, EXIF, GPS"
  }
  ["COMPUTED"]=>
  array(6) {
    ["html"]=>
    string(24) "width="901" height="507""
    ["Height"]=>
    int(507)
    ["Width"]=>
    int(901)
    ["IsColor"]=>
    int(1)
    ["ByteOrderMotorola"]=>
    int(0)
    ["ApertureFNumber"]=>
    string(5) "f/1.9"
  }
  ["IFD0"]=>
  array(4) {
    ["Make"]=>
    string(6) "Xiaomi"
    ["Model"]=>
    string(10) "2306EPN60G"
    ["Exif_IFD_Pointer"]=>
    int(84)
    ["GPS_IFD_Pointer"]=>
    int(388)
  }
  ["EXIF"]=>
  array(17) {
    ["ExposureTime"]=>
    string(12) "2003/5000000"
    ["FNumber"]=>
    string(5) "19/10"
    ["ExposureProgram"]=>
    int(2)
    ["ISOSpeedRatings"]=>
    int(51)
    ["ExifVersion"]=>
    string(4) "0220"
    ["DateTimeDigitized"]=>
    string(19) "2025:07:13 10:35:38"
    ["ShutterSpeedValue"]=>
    string(8) "2257/200"
    ["ApertureValue"]=>
    string(5) "37/20"
    ["BrightnessValue"]=>
    string(6) "103/10"
    ["ExposureBiasValue"]=>
    string(3) "0/1"
    ["MaxApertureValue"]=>
    string(5) "37/20"
    ["MeteringMode"]=>
    int(2)
    ["Flash"]=>
    int(0)
    ["FocalLength"]=>
    string(6) "173/25"
    ["WhiteBalance"]=>
    int(0)
    ["DigitalZoomRatio"]=>
    string(3) "1/1"
    ["FocalLengthIn35mmFilm"]=>
    int(24)
  }
  ["GPS"]=>
  array(4) {
    ["GPSLatitudeRef"]=>
    string(1) "N"
    ["GPSLatitude"]=>
    string(19) "2909560114/90856023"
    ["GPSLongitudeRef"]=>
    string(1) "E"
    ["GPSLongitude"]=>
    string(19) "2064873617/59081709"
  }
}
array(4) {
  ["FILE"]=>
  array(6) {
    ["FileName"]=>
    string(12) "exif-gps.jpg"
    ["FileDateTime"]=>
    int(1753348800)
    ["FileSize"]=>
    int(665)
    ["FileType"]=>
    int(2)
    ["MimeType"]=>
    string(10) "image/jpeg"
    ["SectionsFound"]=>
    string(18) "ANY_TAG, IFD0, GPS"
  }
  ["COMPUTED"]=>
  array(5) {
    ["html"]=>
    string(22) "width="40" height="10""
    ["Height"]=>
    int(10)
    ["Width"]=>
    int(40)
    ["IsColor"]=>
    int(1)
    ["ByteOrderMotorola"]=>
    int(1)
  }
  ["IFD0"]=>
  array(1) {
    ["GPS_IFD_Pointer"]=>
    int(26)
  }
  ["GPS"]=>
  array(8) {
    ["GPSVersion"]=>
    string(4) ""
    ["GPSLatitudeRef"]=>
    string(1) "N"
    ["GPSLatitude"]=>
    array(3) {
      [0]=>
      string(4) "88/1"
      [1]=>
      string(4) "31/1"
      [2]=>
      string(3) "5/1"
    }
    ["GPSLongitudeRef"]=>
    string(1) "W"
    ["GPSLongitude"]=>
    array(3) {
      [0]=>
      string(4) "21/1"
      [1]=>
      string(3) "7/1"
      [2]=>
      string(8) "6213/250"
    }
    ["GPSAltitudeRef"]=>
    string(1) ""
    ["GPSAltitude"]=>
    string(12) "103993/33102"
    ["GPSDOP"]=>
    string(3) "5/1"
  }
}

string(19) "2909560114/90856023" (but loc is supposed to be an array of 3 items)

Seems like the issue is that the file has decimal value for the gps coordinates, but this is not according to spec: https://exiv2.org/tags.html

Indicates the latitude. The latitude is expressed as three RATIONAL values giving the degrees, minutes, and seconds, respectively. When degrees, minutes and seconds are expressed, the format is dd/1,mm/1,ss/1. When degrees and minutes are used and, for example, fractions of minutes are given up to two decimal places, the format is dd/1,mmmm/100,0/1.

GPS is supposed to be 3 rational values (dms), not 1 rational value (decimal).

https://exiftool.org/TagNames/GPS.html
This too says rational64u[3], yet the php exif shows that it is returning a single value for this field in this file ?

https://github.com/CXuesong/WikiClientLibrary/issues/120#issuecomment-3112913578 includes the uncropped original, which seems to show that somewhere/something is stripping some of the data.

GPS Latitude Ref                : North
GPS Speed                       : 0
GPS Altitude Ref                : Above Sea Level
GPS Processing Method           : network
GPS Speed Ref                   : km/h
GPS Version ID                  : 2.2.0.0
GPS Longitude Ref               : East
GPS Time Stamp                  : 07:35:19
GPS Date Stamp                  : 2025:07:13
GPS Altitude                    : 0 m Above Sea Level
GPS Date/Time                   : 2025:07:13 07:35:19Z
GPS Latitude                    : 32 deg 1' 25.88" N
GPS Longitude                   : 34 deg 56' 58.04" E
GPS Position                    : 32 deg 1' 25.88" N, 34 deg 56' 58.04" E

And it's processed correctly by exif_read_data:

array(7) {
  ["FILE"]=>
  array(6) {
    ["FileName"]=>
    string(50) "470248154-669aeaad-b61c-40e4-84c0-73208800c6a4.jpg"
    ["FileDateTime"]=>
    int(1753355030)
    ["FileSize"]=>
    int(4730061)
    ["FileType"]=>
    int(2)
    ["MimeType"]=>
    string(10) "image/jpeg"
    ["SectionsFound"]=>
    string(44) "ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS, INTEROP"
  }
  ["COMPUTED"]=>
  array(8) {
    ["html"]=>
    string(26) "width="4096" height="2304""
    ["Height"]=>
    int(2304)
    ["Width"]=>
    int(4096)
    ["IsColor"]=>
    int(1)
    ["ByteOrderMotorola"]=>
    int(0)
    ["ApertureFNumber"]=>
    string(5) "f/1.9"
    ["Thumbnail.FileType"]=>
    int(2)
    ["Thumbnail.MimeType"]=>
    string(10) "image/jpeg"
  }
  ["IFD0"]=>
  array(17) {
    ["UndefinedTag:0x9999"]=>
    string(131) "{"mirror":false,"sensorType":"rear","Hdr":"auto","OpMode":36866,"smallPicture":false,"AIScene":0,"filterId":66048,"zoomMultiple":1}"
    ["UndefinedTag:0x889A"]=>
    string(1) ""
    ["ImageLength"]=>
    int(2304)
    ["Make"]=>
    string(6) "Xiaomi"
    ["Orientation"]=>
    int(1)
    ["DateTime"]=>
    string(19) "2025:07:13 10:35:38"
    ["GPS_IFD_Pointer"]=>
    int(5940)
    ["YResolution"]=>
    string(4) "72/1"
    ["XResolution"]=>
    string(4) "72/1"
    ["ImageWidth"]=>
    int(4096)
    ["Model"]=>
    string(10) "2306EPN60G"
    ["Software"]=>
    string(27) "MediaTek Camera Application"
    ["ImageDescription"]=>
    NULL
    ["YCbCrPositioning"]=>
    int(2)
    ["Exif_IFD_Pointer"]=>
    int(479)
    ["ResolutionUnit"]=>
    int(2)
    ["UndefinedTag:0x9A00"]=>
    string(10) "Xiaomi 13T"
  }
  ["THUMBNAIL"]=>
  array(11) {
    ["YResolution"]=>
    string(4) "72/1"
    ["Orientation"]=>
    int(1)
    ["Compression"]=>
    int(6)
    ["JPEGInterchangeFormat"]=>
    int(6419)
    ["JPEGInterchangeFormatLength"]=>
    int(21504)
    ["XResolution"]=>
    string(4) "72/1"
    ["Model"]=>
    string(10) "2306EPN60G"
    ["Make"]=>
    string(6) "Xiaomi"
    ["YCbCrPositioning"]=>
    int(2)
    ["ResolutionUnit"]=>
    int(2)
    ["DateTime"]=>
    string(19) "2025:07:13 10:35:38"
  }
  ["EXIF"]=>
  array(41) {
    ["ExifVersion"]=>
    string(4) "0220"
    ["ApertureValue"]=>
    string(7) "185/100"
    ["UndefinedTag:0x9999"]=>
    string(131) "{"mirror":false,"sensorType":"rear","Hdr":"auto","OpMode":36866,"smallPicture":false,"AIScene":0,"filterId":66048,"zoomMultiple":1}"
    ["ExposureBiasValue"]=>
    string(4) "0/10"
    ["ExposureProgram"]=>
    int(2)
    ["ColorSpace"]=>
    int(65535)
    ["UndefinedTag:0x889A"]=>
    string(1) ""
    ["MaxApertureValue"]=>
    string(7) "185/100"
    ["ExifImageLength"]=>
    int(2304)
    ["BrightnessValue"]=>
    string(6) "103/10"
    ["DateTimeOriginal"]=>
    string(19) "2025:07:13 10:35:38"
    ["FlashPixVersion"]=>
    string(4) "0100"
    ["UndefinedTag:0xA661"]=>
    string(3) "163"
    ["UndefinedTag:0x889D"]=>
    string(6) "Madrid"
    ["MakerNote"]=>
    string(6) "Xiaomi"
    ["SubSecTimeOriginal"]=>
    string(3) "781"
    ["WhiteBalance"]=>
    int(0)
    ["InteroperabilityOffset"]=>
    int(6197)
    ["ExposureMode"]=>
    int(0)
    ["ExposureTime"]=>
    string(17) "400600/1000000000"
    ["UndefinedTag:0x9010"]=>
    string(6) "+03:00"
    ["Flash"]=>
    int(0)
    ["SubSecTime"]=>
    string(3) "781"
    ["FNumber"]=>
    string(9) "1900/1000"
    ["UndefinedTag:0x9AAA"]=>
    string(4608) "풁I��gEy�L��a
m*      :�mTvEN�F��|��/x��?=��Wl`D���V^�͋2��    ����j�F!�0��J�s��}�
K�@��j                                      P�{Z8&H�d{�n&N�     ������
��>�,s����A�Vk�P�O�p-_˅�����V�%k��1����~����F%Y����<�w;�>~�����K�;m��~�3��?0(dȊ?�$mo���O���>�o�-�
                                                                                                 J�l�'�0���������Hj����࿽��喰�3d�N|��W�y�����c�o��x�o��Q�xS�a5f�AER�5����`[�[a�^,kz#����mK�I�
d����x  �NZ=��<&r�iY.JF�ì%[e�oa�.z0����p�S��r|�6��F>Iti����.��h�Nr ��GFč���˷M+���ded�%��"y��۠l��Xu�2l�jJv��nChf�4|'L��Y�L�^{a��!�J��(nD��       ;��M!��lLs���w4�~���
4��Q���                                                                                                                                                             �4k7�9 �bX���@O�kb�;u�U������q�J�2�EV�y��,���k�*-�I��W"�;"���.�(@�٢r����9�
f莍�E�X��/��D�/�l�����Y��4�-oX��.�+M�iJ�L�}����);�+�~)
                                                      �H��`
                                                           "�׸�I�_��`e?��������C��W�l�Jj��$С�u�Cu׷ـ4�ez�I����w���.�o<˟�8�(��/'O�EN`�(��hx�Fz�`OJNY8]1뎲=!�._RZ=u�nM&:����%]3�
                                                                                                                                                                               =��nlxL�ue��7��!��
�y�~�`Y��&�͑�t8���b�$5��b�H���'*=W��>�/X�U9�|C:��                                                                                                                                               I�g%�rV�+ɅP�
IÄ�:���_}5}���J�`)��(�i�^)Q���  C=!} \t �n���W���oeφeD��������&���uԆy�D��x���X����k�+���ij���s�'rQFTZ�^n�ߵD����Q�� ��E��ë=���#�,{�H_��`�,���0JhlmM�<�6��{kd���3~[��UE�˿��믾�o�FK�ۚZ�Z�IW:[�.U���֪�ʅ�<����ئ���;��9 OI�0��,z��`�W-rDv���|Ε�3>E  p(�O��J�        EK�{�C���p�U����]P�D�>�{�<G����6��I+]J<AP�ڦ�JE��=���    *�8�\��7��d:��5=Z�(�F��5-t~4S�\����n(+���yb�,��V-����m�U'�k�y��0] KK�AdF��^É-�]))�e�vE"�DQ�te�����������e�67X=�;[�=F\��kF����=^�{�d�o��8W3)�|�@��؀���W������.�}��x�1����\�E�g"O��:����a��
]Ø�Q_��V�6k�t�0��ώXy�Cc16��2OSigk�)Q�oء�,ck��t  
�\LɁX���&�}��h���B����b/�|�z�ǟY3�3t���n�        ���VϤ�'jO�
                                                          �0��~G�X�5e@ݍ�=�zeȕ�c��pV*c��D������i)/{�l��J>n�)�նMGuJԲf'����X�r9�ZSշcQn�y�`���Ơ7�,����S,I˟^h0bB)�"~��>��]��&OU�1lI4+��K���o.�1h*�!�o���K��g�90�5����cI^��ҠU�V��mLeM42�D�ѹ��:F쒵miBU/nB�b�.滒��1kN�o���Ue{����#<V  ����~Y�ղ��Zz��~�DU3q�T��I��Ѝ��E��l]�����Vr�� ^ѐf�
     �_;Ӆ�Q]�ZmV�W&Q���lw]��&�MH�z�+��HB��m
��6�jb<�%�C���L������Z���!abg�<��       ��z��?
                                              ��s��(�8�O�_1�T=���HD�BA�B���=�2wa�>۩uD��_�DP���>�]�
                                                                                                   ��C������ē�ڸ�Y ��ô�j
�Z4a��H�*�U΀Q�f�HF�W������R
                           �J�v3m\/��L� �f��J�߀l����<6]Yeb�ĵ�­�����!�>�Jzg�I�4!݆�W�F�F��G&�+�Zء���D�#��&��
                                                                                                          r�tn���R>n��6�����w
%�q�)�a�r֗�km1�!                                                                                                             ��Ufo�<w�(�xs������Q�����A�!�i��f
��&f�   ����_��ָi_�^g�rW\�Ɉ�¶�]�m��=�/��g��
۾i��ި��EHI��0/B'��b�          �7ĸ��i��Y�����?��b����Y~�A�HZ�
����q��2���
           ���U�y Ņ����*ƺQk�+T)�Ț��ùg�}(�8���
oK�;��Xd��.V���r���G��iF�[a��>�#(���P��Xq�v�Rl����*��4��!`�"U��r�x�Җ�E���^6J�:h�yq�oQ8�*���z���X�OT9�
                                                                                                      q��
L-�$G�f�^S*�0:�۩&3�6�t������{�J������sߐ��k�Y�5
\��h���*��'�>��,�]�H��0��FIvh�
                              )ܚ��7�J���^��\����ժ�&��Tr�R��]̌�dƣN>�����G.�"�Y�)��I��
s^��(7V��?� U�n�yk�-2���q�zTx_����{�Z$�KDX:��'������ȩ!@�wQ��7��ZK`ߖ}K%sLc+*�����+]��z�z��߸Q�w�#���σ�카^���{k^8,��B}�"X;A��J�� r�p�Kwo͟0�_��V��s���]|;������rī�"G��\$�އ����!qg��Wg�:�����0���{��0���cc|D��ղeSȑJ��G�+UR6�țI'����I��X�Tf��a�Ջ�.�Ci�M �R���t)�^�b�q(~�nk~њ$�Qa:��d�m�-s���ci;�J?�G'�6�
���;&2�i��a�p�$S�^�k\��C�!d�Cb��h�I��(��y�L_Wl���� 9*s��0�T�i;�!Oe��L�}-c'�-[�3�/I�["�`T��5�=.A�f^<
�l�1��&����ƸUƊ�37b�\�⡒���1�q!E�C�Z��%������.o@��1��M�����ϧ5uc��`�%�<��N�,/�b�xEw�(�*��={�mfa"��((�aʱ�  ���#�k������Kn�������Y��sz���w?Yj�n���I��n��    xKs�eu�aw�M��}�*�Y�tю^EcZjU����p�)A���<�}+����x�w�o�t�ni��>2ڶm5�X������kfF �a�� �D�%�����z��
                                                                               �ՠ?�:��C���RdŲ�B?�5      h���z���ڻn:(���gq�Aж�
+J��������`9��c�6�"�ޘ+����h�K�k!k����B��.��&H��?�])�H�x'#�8"j�3=&>�
                                  M�0���o�Bu���J��]�����q�*���)�U��&��T����w:+xc�z�Md�>�5�r�wO�٥6R\qǯs�N�6��#cL�
                                                                                                                ���%�U��Zmʹ&@G�7)��{x��v����X�����PbU+e�9ɬ�
                                                                                                                                                           ����wl��I�>��ؽ��#h�t�]l�T0����<��|[��4�7�)�
                                                                                                                                                                                                      ��^��bTV�R��#a�[�v�~�k�h�t�$oz�Iӄ�TL��
                                                                                                                                                                                                                                            p�eIrت�'F��L�ᗭY��2��R�Z<g�~�v9F&�k�(���p�

�x�I���t����o��
               l�����Qv����늷�����%c�?>��U�5|!N���6���Q��       �[�Gúڬ���������W$�P���[՘�����z�Y\Ȣ�+��l�"uW`(¡��O���<
                                                                                                                     �m(��9ȋ�М�����؜x����"+�W.�_{@�y7)�,&<K���n<&1���|
                                                                                                                                                                      �֗���B�u��.��{�Λ[��1��m�CH�8g�|
���V����#���pFE)�~�v��핌"
    ["ExifImageWidth"]=>
    int(4096)
    ["ISOSpeedRatings"]=>
    int(51)
    ["ComponentsConfiguration"]=>
    string(4) ""
    ["UndefinedTag:0x9012"]=>
    string(6) "+03:00"
    ["FocalLengthIn35mmFilm"]=>
    int(24)
    ["SubSecTimeDigitized"]=>
    string(3) "781"
    ["DigitalZoomRatio"]=>
    string(7) "100/100"
    ["DateTimeDigitized"]=>
    string(19) "2025:07:13 10:35:38"
    ["ShutterSpeedValue"]=>
    string(10) "11285/1000"
    ["MeteringMode"]=>
    int(2)
    ["FocalLength"]=>
    string(9) "6920/1000"
    ["UndefinedTag:0x8895"]=>
    int(0)
    ["UndefinedTag:0x9011"]=>
    string(6) "+03:00"
    ["SceneCaptureType"]=>
    int(0)
    ["LightSource"]=>
    int(255)
    ["UndefinedTag:0x9A00"]=>
    string(10) "Xiaomi 13T"
  }
  ["GPS"]=>
  array(12) {
    ["GPSLatitude"]=>
    array(3) {
      [0]=>
      string(4) "32/1"
      [1]=>
      string(3) "1/1"
      [2]=>
      string(18) "258783600/10000000"
    }
    ["GPSAltitude"]=>
    string(7) "0/10000"
    ["GPSLatitudeRef"]=>
    string(1) "N"
    ["GPSSpeed"]=>
    string(7) "0/10000"
    ["GPSAltitudeRef"]=>
    string(1) ""
    ["GPSProcessingMode"]=>
    string(7) "network"
    ["GPSSpeedRef"]=>
    string(1) "K"
    ["GPSVersion"]=>
    string(4) ""
    ["GPSLongitudeRef"]=>
    string(1) "E"
    ["GPSTimeStamp"]=>
    array(3) {
      [0]=>
      string(3) "7/1"
      [1]=>
      string(4) "35/1"
      [2]=>
      string(4) "19/1"
    }
    ["GPSLongitude"]=>
    array(3) {
      [0]=>
      string(4) "34/1"
      [1]=>
      string(4) "56/1"
      [2]=>
      string(18) "580434000/10000000"
    }
    ["GPSDateStamp"]=>
    string(10) "2025:07:13"
  }
  ["INTEROP"]=>
  array(2) {
    ["InterOperabilityIndex"]=>
    string(3) "R98"
    ["InterOperabilityVersion"]=>
    string(4) "0100"
  }
}

And that passes through exifGPStoNumber fine...

https://github.com/CXuesong/WikiClientLibrary/issues/120#issuecomment-3112913578 includes the uncropped original, which seems to show that somewhere/something is stripping some of the data.

Taking that, importing to Google Photos, cropping it similarly... And then putting it through MW is fine.

470248154-669aeaad-b61c-40e4-84c0-73208800c6a4(1).jpg (2,048×1,028 px, 560 KB)

Change #1172815 had a related patch set uploaded (by TheDJ; author: TheDJ):

[mediawiki/core@master] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1172815

I’ve played around a bit yesterday. Kinda up in arms on whether to ignore this data, or do a best effort of allowing it. For instance, i’m not really sure if the ref (direction) info in a case like this can even be relied on.

I might read the exiftool code today, figure out what they do.

Change #1172815 merged by jenkins-bot:

[mediawiki/core@master] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1172815

Change #1173400 had a related patch set uploaded (by Jforrester; author: TheDJ):

[mediawiki/core@REL1_44] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173400

Change #1173402 had a related patch set uploaded (by Reedy; author: TheDJ):

[mediawiki/core@REL1_43] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173402

Change #1173400 merged by jenkins-bot:

[mediawiki/core@REL1_44] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173400

Change #1173416 had a related patch set uploaded (by Reedy; author: TheDJ):

[mediawiki/core@REL1_39] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173416

Change #1173416 merged by jenkins-bot:

[mediawiki/core@REL1_39] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173416

Change #1173402 merged by jenkins-bot:

[mediawiki/core@REL1_43] Exif: Handle malformed gps tags

https://gerrit.wikimedia.org/r/1173402

Jdforrester-WMF assigned this task to TheDJ.
Jdforrester-WMF subscribed.

Provisionally (mostly) fixed?

Change #1172270 abandoned by Reedy:

[mediawiki/core@master] WIP: Add test for file that fails in Exif::exifGPStoNumber()

https://gerrit.wikimedia.org/r/1172270