Skip to content

Commit

Permalink
Fix ArgumentOutOfRangeException when parsing invalid escape \u \x in …
Browse files Browse the repository at this point in the history
…strings (#121)
  • Loading branch information
xoofx committed Mar 8, 2019
1 parent 8133657 commit 0f02805
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 15 deletions.
12 changes: 6 additions & 6 deletions src/Scriban.Tests/TestLexer.cs
Expand Up @@ -638,37 +638,37 @@ public void ParseStringInvalid()
var lexer = new Lexer("{{ '\\u' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '\\u1' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '\\u12' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '\\u123' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '\\x' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '\\x1' }}");
var tokens = lexer.ToList();
Assert.True(lexer.HasErrors);
StringAssert.Contains("Unexpected escape character", lexer.Errors.First().Message);
StringAssert.Contains("Unexpected hex number", lexer.Errors.First().Message);
}
{
var lexer = new Lexer("{{ '");
Expand Down
9 changes: 8 additions & 1 deletion src/Scriban.Tests/TestParser.cs
Expand Up @@ -45,14 +45,21 @@ public void TestRoundtrip1()
}

[Test]
public void TestLiquidError()
public void TestLiquidMissingClosingBrace()
{
var template = Template.ParseLiquid("{%endunless");
Assert.True(template.HasErrors);
Assert.AreEqual(1, template.Messages.Count);
Assert.AreEqual("<input>(1,3) : error : Unable to find a pending `unless` for this `endunless`", template.Messages[0].ToString());
}

[Test]
public void TestLiquidInvalidStringEscape()
{
var template = Template.ParseLiquid(@"{%""\u""");
Assert.True(template.HasErrors);
}

[Test]
public void RoundtripFunction()
{
Expand Down
2 changes: 2 additions & 0 deletions src/Scriban/Parsing/Lexer.cs
Expand Up @@ -1299,6 +1299,7 @@ private void ReadString()
}
}
}
AddError($"Unexpected hex number `{c}` following `\\u`. Expecting `\\u0000` to `\\uffff`.", _position, _position);
break;
case 'x':
end = _position;
Expand All @@ -1315,6 +1316,7 @@ private void ReadString()
continue;
}
}
AddError($"Unexpected hex number `{c}` following `\\x`. Expecting `\\x00` to `\\xff`", _position, _position);
break;

}
Expand Down
15 changes: 9 additions & 6 deletions src/Scriban/Parsing/Parser.Terminals.cs
Expand Up @@ -155,19 +155,22 @@ private ScriptLiteral ParseString()
case 'u':
{
i++;
var value = (text[i++].HexToInt() << 12) +
(text[i++].HexToInt() << 8) +
(text[i++].HexToInt() << 4) +
text[i].HexToInt();
int value = 0;
if (i < text.Length) value = text[i++].HexToInt();
if (i < text.Length) value = (value << 4) | text[i++].HexToInt();
if (i < text.Length) value = (value << 4) | text[i++].HexToInt();
if (i < text.Length) value = (value << 4) | text[i].HexToInt();

// Is it correct?
builder.Append(ConvertFromUtf32(value));
break;
}
case 'x':
{
i++;
var value = (text[i++].HexToInt() << 4) +
text[i++].HexToInt();
int value = 0;
if (i < text.Length) value = text[i++].HexToInt();
if (i < text.Length) value = (value << 4) | text[i].HexToInt();
builder.Append((char) value);
break;
}
Expand Down
5 changes: 3 additions & 2 deletions src/Scriban/Parsing/Util.cs
@@ -1,4 +1,4 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// Copyright (c) Alexandre Mutel. All rights reserved.
// Licensed under the BSD-Clause 2 license.
// See license.txt file in the project root for full license information.
using System;
Expand Down Expand Up @@ -28,7 +28,8 @@ public static int HexToInt(this char c)
{
return c - 'A' + 10;
}
throw new ArgumentOutOfRangeException(nameof(c), $"The character '{c}' is not an hexa [0a-fA-F] character");
// Don't throw an exception as we are checking and logging an error if IsHex is false already
return 0;
}
}
}

0 comments on commit 0f02805

Please sign in to comment.