Skip to content

Commit 51cb212

Browse files
authored
Fix for bug #1592 (UPDATED) (#1623)
* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length
1 parent 3025824 commit 51cb212

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/PhpSpreadsheet/Reader/Xls.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,6 +2973,9 @@ private function readSst(): void
29732973
// offset within (spliced) record data
29742974
$pos = 0;
29752975

2976+
// Limit global SST position, further control for bad SST Length in BIFF8 data
2977+
$limitposSST = 0;
2978+
29762979
// get spliced record data
29772980
$splicedRecordData = $this->getSplicedRecordData();
29782981

@@ -2986,8 +2989,17 @@ private function readSst(): void
29862989
$nm = self::getInt4d($recordData, 4);
29872990
$pos += 4;
29882991

2992+
// look up limit position
2993+
foreach ($spliceOffsets as $spliceOffset) {
2994+
// it can happen that the string is empty, therefore we need
2995+
// <= and not just <
2996+
if ($pos <= $spliceOffset) {
2997+
$limitposSST = $spliceOffset;
2998+
}
2999+
}
3000+
29893001
// loop through the Unicode strings (16-bit length)
2990-
for ($i = 0; $i < $nm; ++$i) {
3002+
for ($i = 0; $i < $nm && $pos < $limitposSST; ++$i) {
29913003
// number of characters in the Unicode string
29923004
$numChars = self::getUInt2d($recordData, $pos);
29933005
$pos += 2;
@@ -3020,7 +3032,7 @@ private function readSst(): void
30203032
// expected byte length of character array if not split
30213033
$len = ($isCompressed) ? $numChars : $numChars * 2;
30223034

3023-
// look up limit position
3035+
// look up limit position - Check it again to be sure that no error occurs when parsing SST structure
30243036
foreach ($spliceOffsets as $spliceOffset) {
30253037
// it can happen that the string is empty, therefore we need
30263038
// <= and not just <

tests/PhpSpreadsheetTests/Reader/XlsTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,39 @@ public function testLoadXlsBug1505(): void
4343
self::assertEquals($sheet->getCell('A1')->getFormattedValue(), $newsheet->getCell('A1')->getFormattedValue());
4444
self::assertEquals($sheet->getCell("$col$row")->getFormattedValue(), $newsheet->getCell("$col$row")->getFormattedValue());
4545
}
46+
47+
/**
48+
* Test load Xls file with invalid length in SST map.
49+
*/
50+
public function testLoadXlsBug1592(): void
51+
{
52+
$filename = 'tests/data/Reader/XLS/bug1592.xls';
53+
$reader = new Xls();
54+
// When no fix applied, spreadsheet is not loaded
55+
$spreadsheet = $reader->load($filename);
56+
$sheet = $spreadsheet->getActiveSheet();
57+
$col = $sheet->getHighestColumn();
58+
$row = $sheet->getHighestRow();
59+
60+
$newspreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
61+
$newsheet = $newspreadsheet->getActiveSheet();
62+
$newcol = $newsheet->getHighestColumn();
63+
$newrow = $newsheet->getHighestRow();
64+
65+
self::assertEquals($spreadsheet->getSheetCount(), $newspreadsheet->getSheetCount());
66+
self::assertEquals($sheet->getTitle(), $newsheet->getTitle());
67+
self::assertEquals($sheet->getColumnDimensions(), $newsheet->getColumnDimensions());
68+
self::assertEquals($col, $newcol);
69+
self::assertEquals($row, $newrow);
70+
71+
$rowIterator = $sheet->getRowIterator();
72+
73+
foreach ($rowIterator as $row) {
74+
foreach ($row->getCellIterator() as $cell) {
75+
$valOld = $cell->getFormattedValue();
76+
$valNew = $newsheet->getCell($cell->getCoordinate())->getFormattedValue();
77+
self::assertEquals($valOld, $valNew);
78+
}
79+
}
80+
}
4681
}

tests/data/Reader/XLS/bug1592.xls

20.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)