Skip to content

Commit

Permalink
Fix for bug #1592 (UPDATED) (#1623)
Browse files Browse the repository at this point in the history
* Fix for Xls when BIFF8 SST (FCh) has bad Shared string length
  • Loading branch information
ggiovinazzo authored Dec 17, 2020
1 parent 3025824 commit 51cb212
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/PhpSpreadsheet/Reader/Xls.php
Original file line number Diff line number Diff line change
Expand Up @@ -2973,6 +2973,9 @@ private function readSst(): void
// offset within (spliced) record data
$pos = 0;

// Limit global SST position, further control for bad SST Length in BIFF8 data
$limitposSST = 0;

// get spliced record data
$splicedRecordData = $this->getSplicedRecordData();

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

// look up limit position
foreach ($spliceOffsets as $spliceOffset) {
// it can happen that the string is empty, therefore we need
// <= and not just <
if ($pos <= $spliceOffset) {
$limitposSST = $spliceOffset;
}
}

// loop through the Unicode strings (16-bit length)
for ($i = 0; $i < $nm; ++$i) {
for ($i = 0; $i < $nm && $pos < $limitposSST; ++$i) {
// number of characters in the Unicode string
$numChars = self::getUInt2d($recordData, $pos);
$pos += 2;
Expand Down Expand Up @@ -3020,7 +3032,7 @@ private function readSst(): void
// expected byte length of character array if not split
$len = ($isCompressed) ? $numChars : $numChars * 2;

// look up limit position
// look up limit position - Check it again to be sure that no error occurs when parsing SST structure
foreach ($spliceOffsets as $spliceOffset) {
// it can happen that the string is empty, therefore we need
// <= and not just <
Expand Down
35 changes: 35 additions & 0 deletions tests/PhpSpreadsheetTests/Reader/XlsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,39 @@ public function testLoadXlsBug1505(): void
self::assertEquals($sheet->getCell('A1')->getFormattedValue(), $newsheet->getCell('A1')->getFormattedValue());
self::assertEquals($sheet->getCell("$col$row")->getFormattedValue(), $newsheet->getCell("$col$row")->getFormattedValue());
}

/**
* Test load Xls file with invalid length in SST map.
*/
public function testLoadXlsBug1592(): void
{
$filename = 'tests/data/Reader/XLS/bug1592.xls';
$reader = new Xls();
// When no fix applied, spreadsheet is not loaded
$spreadsheet = $reader->load($filename);
$sheet = $spreadsheet->getActiveSheet();
$col = $sheet->getHighestColumn();
$row = $sheet->getHighestRow();

$newspreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
$newsheet = $newspreadsheet->getActiveSheet();
$newcol = $newsheet->getHighestColumn();
$newrow = $newsheet->getHighestRow();

self::assertEquals($spreadsheet->getSheetCount(), $newspreadsheet->getSheetCount());
self::assertEquals($sheet->getTitle(), $newsheet->getTitle());
self::assertEquals($sheet->getColumnDimensions(), $newsheet->getColumnDimensions());
self::assertEquals($col, $newcol);
self::assertEquals($row, $newrow);

$rowIterator = $sheet->getRowIterator();

foreach ($rowIterator as $row) {
foreach ($row->getCellIterator() as $cell) {
$valOld = $cell->getFormattedValue();
$valNew = $newsheet->getCell($cell->getCoordinate())->getFormattedValue();
self::assertEquals($valOld, $valNew);
}
}
}
}
Binary file added tests/data/Reader/XLS/bug1592.xls
Binary file not shown.

0 comments on commit 51cb212

Please sign in to comment.