Skip to content

Commit 99f59c5

Browse files
committed
Drowning in Warning Messages with Corrupt Xls File
Fix #4647. Xls file is corrupt - PhpSpreadsheet tries to extract a substring using array notation, but the index is out of bounds. Php treats this as a warning situation, so continues to process, leading to an onslaught of warning messages. We could change to use the `substr` function rather than array notation, but that seems inappropriate - it would be better to throw an exception and have the user fix the file. In the file posted with the issue, opening it with Excel, and responding yes when it asks if it's okay to clean up the corruption, yields a usable file. Unfortunately, that file weighs in at 28MB, much too large for our test suite. So, no new unit tests accompany this change, but it has been tested. Tests are added to `getUint2d`, which seems to be the source of the problem in the sample file, and, for good measure, `getInt2d` and `getInt4d`. There may be other sources of similar corruption, but we'll stick with what's in front of our nose.
1 parent 996de17 commit 99f59c5

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

src/PhpSpreadsheet/Reader/XlsBase.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,20 @@ protected function decodeCodepage(string $string): string
368368
return StringHelper::convertEncoding($string, 'UTF-8', $this->codepage);
369369
}
370370

371+
protected static function confirmPos(string $data, int $pos): void
372+
{
373+
if ($pos >= strlen($data)) {
374+
throw new PhpSpreadsheetException('File appears to be corrupt'); //* @codeCoverageIgnore
375+
}
376+
}
377+
371378
/**
372379
* Read 16-bit unsigned integer.
373380
*/
374381
public static function getUInt2d(string $data, int $pos): int
375382
{
383+
self::confirmPos($data, $pos + 1);
384+
376385
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8);
377386
}
378387

@@ -381,6 +390,8 @@ public static function getUInt2d(string $data, int $pos): int
381390
*/
382391
public static function getInt2d(string $data, int $pos): int
383392
{
393+
self::confirmPos($data, $pos + 1);
394+
384395
return unpack('s', $data[$pos] . $data[$pos + 1])[1]; // @phpstan-ignore-line
385396
}
386397

@@ -389,6 +400,8 @@ public static function getInt2d(string $data, int $pos): int
389400
*/
390401
public static function getInt4d(string $data, int $pos): int
391402
{
403+
self::confirmPos($data, $pos + 3);
404+
392405
// FIX: represent numbers correctly on 64-bit system
393406
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
394407
// Changed by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems

0 commit comments

Comments
 (0)