From a1a1077677ae2d3f5859de03f95b8620865e7c35 Mon Sep 17 00:00:00 2001 From: Adrien Loison Date: Mon, 5 Oct 2015 17:08:11 +0200 Subject: [PATCH] Fix infinite loop for CSV with all lines empty Only occured with multiline CSV files --- src/Spout/Reader/CSV/RowIterator.php | 34 +++++++++++---------- tests/Spout/Reader/CSV/ReaderTest.php | 23 ++++++++++++++ tests/bootstrap.php | 3 ++ tests/resources/csv/csv_all_lines_empty.csv | 2 ++ tests/resources/csv/csv_empty.csv | 0 5 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 tests/resources/csv/csv_all_lines_empty.csv create mode 100644 tests/resources/csv/csv_empty.csv diff --git a/src/Spout/Reader/CSV/RowIterator.php b/src/Spout/Reader/CSV/RowIterator.php index 0c9fc07..b6f897c 100644 --- a/src/Spout/Reader/CSV/RowIterator.php +++ b/src/Spout/Reader/CSV/RowIterator.php @@ -111,26 +111,28 @@ class RowIterator implements IteratorInterface */ public function next() { - $lineData = false; $this->hasReachedEndOfFile = $this->globalFunctionsHelper->feof($this->filePointer); - if (!$this->hasReachedEndOfFile) { - do { - $utf8EncodedLineData = $this->getNextUTF8EncodedLine(); - if ($utf8EncodedLineData !== false) { - $lineData = $this->globalFunctionsHelper->str_getcsv($utf8EncodedLineData, $this->fieldDelimiter, $this->fieldEnclosure); - } - $hasNowReachedEndOfFile = $this->globalFunctionsHelper->feof($this->filePointer); - } while (($lineData === false && !$hasNowReachedEndOfFile) || $this->isEmptyLine($lineData)); + if ($this->hasReachedEndOfFile) { + return; + } - if ($lineData !== false) { - $this->rowDataBuffer = $lineData; - $this->numReadRows++; - } else { - // If we reach this point, it means end of file was reached. - // This happens when the last lines are empty lines. - $this->hasReachedEndOfFile = $hasNowReachedEndOfFile; + do { + $lineData = false; + $utf8EncodedLineData = $this->getNextUTF8EncodedLine(); + if ($utf8EncodedLineData !== false) { + $lineData = $this->globalFunctionsHelper->str_getcsv($utf8EncodedLineData, $this->fieldDelimiter, $this->fieldEnclosure); } + $hasNowReachedEndOfFile = $this->globalFunctionsHelper->feof($this->filePointer); + } while (($lineData === false && !$hasNowReachedEndOfFile) || $this->isEmptyLine($lineData)); + + if ($lineData !== false) { + $this->rowDataBuffer = $lineData; + $this->numReadRows++; + } else { + // If we reach this point, it means end of file was reached. + // This happens when the last lines are empty lines. + $this->hasReachedEndOfFile = $hasNowReachedEndOfFile; } } diff --git a/tests/Spout/Reader/CSV/ReaderTest.php b/tests/Spout/Reader/CSV/ReaderTest.php index b868b1e..00a0f2c 100644 --- a/tests/Spout/Reader/CSV/ReaderTest.php +++ b/tests/Spout/Reader/CSV/ReaderTest.php @@ -142,6 +142,29 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedRows, $allRows); } + /** + * @return array + */ + public function dataProviderForTestReadShouldReadEmptyFile() + { + return [ + ['csv_empty.csv'], + ['csv_all_lines_empty.csv'], + ]; + } + + /** + * @dataProvider dataProviderForTestReadShouldReadEmptyFile + * + * @param string $fileName + * @return void + */ + public function testReadShouldReadEmptyFile($fileName) + { + $allRows = $this->getAllRowsForFile($fileName); + $this->assertEquals([], $allRows); + } + /** * @return void */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 75bf44b..ebe7689 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -3,3 +3,6 @@ require_once(dirname(__DIR__) . '/vendor/autoload.php'); require_once(dirname(__DIR__) . '/tests/Spout/TestUsingResource.php'); require_once(dirname(__DIR__) . '/tests/Spout/ReflectionHelper.php'); + +// Make sure a timezone is set to be able to work with dates +date_default_timezone_set('UTC'); diff --git a/tests/resources/csv/csv_all_lines_empty.csv b/tests/resources/csv/csv_all_lines_empty.csv new file mode 100644 index 0000000..139597f --- /dev/null +++ b/tests/resources/csv/csv_all_lines_empty.csv @@ -0,0 +1,2 @@ + + diff --git a/tests/resources/csv/csv_empty.csv b/tests/resources/csv/csv_empty.csv new file mode 100644 index 0000000..e69de29