Skip to content

Commit

Permalink
Make JsonParser escape character parsing more strict
Browse files Browse the repository at this point in the history
  • Loading branch information
Genteure committed May 7, 2022
1 parent c8e2c2c commit 5856511
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 66 deletions.
3 changes: 2 additions & 1 deletion Jint.Tests/Runtime/JsonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void ShouldParseEscapedCharactersCorrectly(string json, string expectedCh
[InlineData("{true}", "Unexpected token 'true' in JSON at position 1")]
[InlineData("{null}", "Unexpected token 'null' in JSON at position 1")]
[InlineData("{:}", "Unexpected token ':' in JSON at position 1")]
[InlineData("\"\\xah\"", "Expected hexadecimal digit in JSON at position 4")]
[InlineData("\"\\uah\"", "Expected hexadecimal digit in JSON at position 4")]
[InlineData("0123", "Unexpected token '1' in JSON at position 1")] // leading 0 (octal number) not allowed
[InlineData("1e+A", "Unexpected token 'A' in JSON at position 3")]
[InlineData("truE", "Unexpected token 'tru' in JSON at position 0")]
Expand All @@ -55,6 +55,7 @@ public void ShouldParseEscapedCharactersCorrectly(string json, string expectedCh
[InlineData("alpha", "Unexpected token 'a' in JSON at position 0")]
[InlineData("[1,\na]", "Unexpected token 'a' in JSON at position 4")] // multiline
[InlineData("\x06", "Unexpected token '\x06' in JSON at position 0")] // control char
[InlineData("{\"\\v\":1}", "Unexpected token 'v' in JSON at position 3")] // invalid escape sequence
public void ShouldReportHelpfulSyntaxErrorForInvalidJson(string json, string expectedMessage)
{
var engine = new Engine();
Expand Down
99 changes: 34 additions & 65 deletions Jint/Native/Json/JsonParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,11 @@ private static bool IsTrueOrFalseChar(char ch)
;
}

private char ScanHexEscape(char prefix)
private char ScanHexEscape()
{
int code = char.MinValue;

int len = (prefix == 'u') ? 4 : 2;
for (int i = 0; i < len; ++i)
for (int i = 0; i < 4; ++i)
{
if (_index < _length && IsHexDigit(_source.CharCodeAt(_index)))
{
Expand All @@ -100,7 +99,7 @@ private char ScanHexEscape(char prefix)
ThrowError(_index, Messages.ExpectedHexadecimalDigit);
}
}
return (char)code;
return (char) code;
}

private void SkipWhiteSpace()
Expand Down Expand Up @@ -320,68 +319,38 @@ private Token ScanStringLiteral()
{
ch = _source.CharCodeAt(_index++);

if (ch > 0 || !IsLineTerminator(ch))
switch (ch)
{
switch (ch)
{
case 'n':
sb.Append('\n');
break;
case 'r':
sb.Append('\r');
break;
case 't':
sb.Append('\t');
break;
case 'u':
case 'x':
char unescaped = ScanHexEscape(ch);
sb.Append(unescaped);
break;
case 'b':
sb.Append('\b');
break;
case 'f':
sb.Append('\f');
break;
case 'v':
sb.Append('\x0B');
break;

default:
if (IsOctalDigit(ch))
{
int code = "01234567".IndexOf(ch);

if (_index < _length && IsOctalDigit(_source.CharCodeAt(_index)))
{
code = code * 8 + "01234567".IndexOf(_source.CharCodeAt(_index++));

// 3 digits are only allowed when string starts
// with 0, 1, 2, 3
if ("0123".IndexOf(ch) >= 0 &&
_index < _length &&
IsOctalDigit(_source.CharCodeAt(_index)))
{
code = code * 8 + "01234567".IndexOf(_source.CharCodeAt(_index++));
}
}
sb.Append(((char)code).ToString());
}
else
{
sb.Append(ch.ToString());
}
break;
}
}
else
{
++_lineNumber;
if (ch == '\r' && _source.CharCodeAt(_index) == '\n')
{
++_index;
}
case '"':
sb.Append('"');
break;
case '\\':
sb.Append('\\');
break;
case '/':
sb.Append('/');
break;
case 'n':
sb.Append('\n');
break;
case 'r':
sb.Append('\r');
break;
case 't':
sb.Append('\t');
break;
case 'u':
sb.Append(ScanHexEscape());
break;
case 'b':
sb.Append('\b');
break;
case 'f':
sb.Append('\f');
break;
default:
ThrowError(_index - 1, Messages.UnexpectedToken, ch);
break;
}
}
else if (IsLineTerminator(ch))
Expand Down

0 comments on commit 5856511

Please sign in to comment.