diff --git a/src/Parser/Lines.php b/src/Parser/Lines.php index de290c5a..05d3139c 100644 --- a/src/Parser/Lines.php +++ b/src/Parser/Lines.php @@ -43,6 +43,13 @@ public static function process(array $lines) } } + // The input ended while still within a multiline value. Emit what was + // buffered, so that the parser reports the missing closing quote, + // instead of discarding this entry and every line that followed it. + if ($multiline) { + $output[] = \implode("\n", $multilineBuffer); + } + return $output; } diff --git a/tests/Dotenv/DotenvTest.php b/tests/Dotenv/DotenvTest.php index 99494bc7..2a7f567c 100644 --- a/tests/Dotenv/DotenvTest.php +++ b/tests/Dotenv/DotenvTest.php @@ -6,6 +6,7 @@ use Dotenv\Dotenv; use Dotenv\Exception\InvalidEncodingException; +use Dotenv\Exception\InvalidFileException; use Dotenv\Exception\InvalidPathException; use Dotenv\Loader\Loader; use Dotenv\Parser\Parser; @@ -450,6 +451,30 @@ public function testDotenvParseMultilineContainingHash() ); } + public function testDotenvParseUnterminatedDoubleQuote() + { + $this->expectException(InvalidFileException::class); + $this->expectExceptionMessage('Encountered a missing closing quote at ["bar].'); + + Dotenv::parse('FOO="bar'); + } + + public function testDotenvParseUnterminatedDoubleQuoteDoesNotSwallowLaterLines() + { + $this->expectException(InvalidFileException::class); + $this->expectExceptionMessage('Encountered a missing closing quote at ["oops].'); + + Dotenv::parse("A=\"oops\nB=keep"); + } + + public function testDotenvParseUnterminatedDoubleQuoteMatchesSingleQuote() + { + $this->expectException(InvalidFileException::class); + $this->expectExceptionMessage('Encountered a missing closing quote at [\'bar].'); + + Dotenv::parse("FOO='bar"); + } + public function testDotenvParseEmptyCase() { $output = Dotenv::parse('');