Skip to content

Commit 791bc8f

Browse files
committed
Detect missing backslashes further along in the string, fixes #54
1 parent 67f3db2 commit 791bc8f

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

src/Seld/JsonLint/JsonParser.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ public function parse($input, $flags = 0)
202202
$message = "Invalid string";
203203
if ("'" === substr($this->lexer->match, 0, 1)) {
204204
$message .= ", it appears you used single quotes instead of double quotes";
205-
} elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
205+
} elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u](...)?)}', $this->lexer->getFullUpcomingInput(), $match)) {
206206
$message .= ", it appears you have an unescaped backslash at: ".$match[1];
207-
} elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
207+
} elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getFullUpcomingInput())) {
208208
$message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
209209
}
210210
}

src/Seld/JsonLint/Lexer.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ public function getUpcomingInput()
104104
return substr($next, 0, 20) . (\strlen($next) > 20 ? '...' : '');
105105
}
106106

107+
public function getFullUpcomingInput()
108+
{
109+
$next = $this->match;
110+
if (substr($next, 0, 1) === '"' && substr_count($next, '"') === 1) {
111+
$len = \strlen($this->input);
112+
$strEnd = min(strpos($this->input, '"', $this->offset + 1) ?: $len, strpos($this->input, "\n", $this->offset + 1) ?: $len);
113+
$next .= substr($this->input, $this->offset, $strEnd - $this->offset);
114+
} elseif (\strlen($next) < 20) {
115+
$next .= substr($this->input, $this->offset, 20 - \strlen($next));
116+
}
117+
118+
return $next;
119+
}
120+
107121
protected function parseError($str, $hash)
108122
{
109123
throw new \Exception($str);

tests/JsonParserTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,44 @@ public function testErrorOnUnescapedBackslash()
9999
}
100100
}
101101

102+
public function testErrorOnLongUnescapedBackslash()
103+
{
104+
$parser = new JsonParser();
105+
try {
106+
$parser->parse('{
107+
"#3026386-26 - Drush fatal error after upgrading to 8.6.6, 8.5.9, or 7.62: PHP Fatal error: Uncaught TYPO3\PharStreamWrapper\Exception": "https://www.drupal.org/files/issues/2019-01-16/d8-3026386-26.patch"
108+
}');
109+
$this->fail('Invalid unescaped string should be detected');
110+
} catch (ParsingException $e) {
111+
$expected = <<<'EXPECTED'
112+
Parse error on line 1:
113+
{ "#3026386-26 - Drush
114+
----^
115+
Invalid string, it appears you have an unescaped backslash at: \Phar
116+
EXPECTED;
117+
$this->assertEquals($expected, $e->getMessage());
118+
}
119+
}
120+
121+
public function testErrorOnLongUnescapedBackslash2()
122+
{
123+
$parser = new JsonParser();
124+
try {
125+
$parser->parse('{
126+
"#3026386-26 - Drush fatal error after upgrading to 8.6.6, 8.5.9, or 7.62: PHP Fatal error": "https://www.drupal.org/files/issues/201\9-01-16/d8-3026386-26.patch
127+
}');
128+
$this->fail('Invalid unescaped string should be detected');
129+
} catch (ParsingException $e) {
130+
$expected = <<<'EXPECTED'
131+
Parse error on line 2:
132+
...: PHP Fatal error": "https://www.drupal.
133+
----------------------^
134+
Invalid string, it appears you have an unescaped backslash at: \9-01
135+
EXPECTED;
136+
$this->assertEquals($expected, $e->getMessage());
137+
}
138+
}
139+
102140
public function testErrorOnUnterminatedString()
103141
{
104142
$parser = new JsonParser();

0 commit comments

Comments
 (0)