From 6331df6b0c4cde6547f00117221718f376eb1e45 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 18 Jun 2007 14:57:32 +0000 Subject: [PATCH] Fixed forum-17502: exception in C# and VB lexer when a hexadecimal literal is larger than ulong.MaxValue. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.1@2559 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Libraries/NRefactory/NRefactory.sln | 6 +- .../Project/Src/Lexer/CSharp/Lexer.cs | 8 +- .../Project/Src/Lexer/VBNet/Lexer.cs | 84 ++++++++++--------- .../Test/Lexer/CSharp/NumberLexerTest.cs | 4 + .../Test/Lexer/VBNet/LiteralsTests.cs | 32 ++++++- 5 files changed, 90 insertions(+), 44 deletions(-) diff --git a/src/Libraries/NRefactory/NRefactory.sln b/src/Libraries/NRefactory/NRefactory.sln index 9bde0d8af4..ee7ee36f90 100644 --- a/src/Libraries/NRefactory/NRefactory.sln +++ b/src/Libraries/NRefactory/NRefactory.sln @@ -1,5 +1,7 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# SharpDevelop 2.1.0.1865 + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +# SharpDevelop 2.2.0.2532 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryTests", "Test\NRefactoryTests.csproj", "{870115DD-960A-4406-A6B9-600BCDC36A03}" diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs index 9ee7a6b8f8..fc392520b3 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs @@ -289,7 +289,13 @@ namespace ICSharpCode.NRefactory.Parser.CSharp // Try to determine a parsable value using ranges. (Quick hack!) double d = 0; if (ishex) { - d = ulong.Parse(digit, NumberStyles.HexNumber); + ulong result; + if (ulong.TryParse(digit, NumberStyles.HexNumber, null, out result)) { + d = result; + } else { + errors.Error(y, x, String.Format("Can't parse hexadecimal constant {0}", digit)); + return new Token(Tokens.Literal, x, y, stringValue.ToString(), 0); + } } else { if (!Double.TryParse(digit, NumberStyles.Integer, null, out d)) { errors.Error(y, x, String.Format("Can't parse integral constant {0}", digit)); diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs index 4e25eedffd..770bc55f15 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs @@ -12,7 +12,7 @@ using System.Text; namespace ICSharpCode.NRefactory.Parser.VB { - internal class Lexer : AbstractLexer + internal sealed class Lexer : AbstractLexer { bool lineEnd = true; @@ -318,6 +318,7 @@ namespace ICSharpCode.NRefactory.Parser.VB ch = Char.ToUpper(ch, CultureInfo.InvariantCulture); bool unsigned = ch == 'U'; if (unsigned) { + ReaderRead(); // read the U ch = (char)ReaderPeek(); sb.Append(ch); ch = Char.ToUpper(ch, CultureInfo.InvariantCulture); @@ -325,60 +326,65 @@ namespace ICSharpCode.NRefactory.Parser.VB errors.Error(Line, Col, "Invalid type character: U" + ch); } } - if (isokt) { - ReaderRead(); - ulong number = 0L; - for (int i = 0; i < digit.Length; ++i) { - number = number * 8 + digit[i] - '0'; + try { + if (isokt) { + ReaderRead(); + ulong number = 0L; + for (int i = 0; i < digit.Length; ++i) { + number = number * 8 + digit[i] - '0'; + } + if (ch == 'S') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ushort)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (short)number); + } else if (ch == '%' || ch == 'I') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (uint)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (int)number); + } else if (ch == '&' || ch == 'L') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ulong)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (long)number); + } else { + if (number > uint.MaxValue) { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((long)number)); + } else { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((int)number)); + } + } } if (ch == 'S') { + ReaderRead(); if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ushort)number); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt16.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (short)number); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int16.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); } else if (ch == '%' || ch == 'I') { + ReaderRead(); if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (uint)number); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt32.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (int)number); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int32.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); } else if (ch == '&' || ch == 'L') { + ReaderRead(); if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ulong)number); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt64.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (long)number); - } else { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int64.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); + } else if (ishex) { + ulong number = UInt64.Parse(digit, NumberStyles.HexNumber); if (number > uint.MaxValue) { return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((long)number)); } else { return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((int)number)); } } - } - if (ch == 'S') { - ReaderRead(); - if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt16.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int16.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - } else if (ch == '%' || ch == 'I') { - ReaderRead(); - if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt32.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int32.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - } else if (ch == '&' || ch == 'L') { - ReaderRead(); - if (unsigned) - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt64.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - else - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int64.Parse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number)); - } else if (ishex) { - ulong number = UInt64.Parse(digit, NumberStyles.HexNumber); - if (number > uint.MaxValue) { - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((long)number)); - } else { - return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((int)number)); - } + } catch (OverflowException ex) { + errors.Error(Line, Col, ex.Message); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); } } Token nextToken = null; // if we accedently read a 'dot' diff --git a/src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs b/src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs index 6a3abc073e..7b53e21112 100644 --- a/src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs +++ b/src/Libraries/NRefactory/Test/Lexer/CSharp/NumberLexerTest.cs @@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp Assert.AreEqual(Tokens.Literal, t.kind, "Tokens.Literal"); Assert.AreEqual(text, t.val, "value"); Assert.IsNotNull(t.literalValue, "literalValue is null"); + Assert.AreEqual(val.GetType(), t.literalValue.GetType(), "literalValue.GetType()"); Assert.AreEqual(val, t.literalValue, "literalValue"); } @@ -80,12 +81,15 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp GenerateLexer(new StringReader("0xG2F")).NextToken(); // SD2-457 GenerateLexer(new StringReader("0x")).NextToken(); + // hexadecimal integer >ulong.MaxValue + GenerateLexer(new StringReader("0xfedcba98765432100")).NextToken(); } [Test] public void TestLongHexadecimalInteger() { CheckToken("0x4244636f446c6d58", 0x4244636f446c6d58); + CheckToken("0xf244636f446c6d58", 0xf244636f446c6d58); } [Test] diff --git a/src/Libraries/NRefactory/Test/Lexer/VBNet/LiteralsTests.cs b/src/Libraries/NRefactory/Test/Lexer/VBNet/LiteralsTests.cs index ed323342ab..afdee40ce6 100644 --- a/src/Libraries/NRefactory/Test/Lexer/VBNet/LiteralsTests.cs +++ b/src/Libraries/NRefactory/Test/Lexer/VBNet/LiteralsTests.cs @@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.VB Token t = GetSingleToken(text); Assert.AreEqual(tokenType, t.kind, "Tokens.Literal"); Assert.IsNotNull(t.literalValue, "literalValue is null"); + Assert.AreEqual(val.GetType(), t.literalValue.GetType(), "literalValue.GetType()"); Assert.AreEqual(val, t.literalValue, "literalValue"); } @@ -63,8 +64,35 @@ namespace ICSharpCode.NRefactory.Tests.Lexer.VB public void TestHexadecimalInteger() { CheckToken("&H10", Tokens.LiteralInteger, 0x10); - CheckToken("&H10&", Tokens.LiteralInteger, 0x10); - CheckToken("&h3ff&", Tokens.LiteralInteger, 0x3ff); + CheckToken("&H10&", Tokens.LiteralInteger, (long)0x10); + CheckToken("&h3ff%", Tokens.LiteralInteger, 0x3ff); + CheckToken("&h8000s", Tokens.LiteralInteger, short.MinValue); + CheckToken("&h8000us", Tokens.LiteralInteger, (ushort)0x8000); + CheckToken("&HffffFFFF", Tokens.LiteralInteger, -1); + CheckToken("&HffffFFFF%", Tokens.LiteralInteger, -1); + CheckToken("&HffffFFFFui", Tokens.LiteralInteger, uint.MaxValue); + CheckToken("&HffffFFFF&", Tokens.LiteralInteger, (long)uint.MaxValue); + } + + [Test] + public void TestLongHexadecimalInteger() + { + CheckToken("&H4244636f446c6d58", Tokens.LiteralInteger, 0x4244636f446c6d58); + CheckToken("&hf244636f446c6d58", Tokens.LiteralInteger, -989556688574190248); + CheckToken("&hf244636f446c6d58&", Tokens.LiteralInteger, -989556688574190248); + CheckToken("&hf244636f446c6d58ul", Tokens.LiteralInteger, 0xf244636f446c6d58); + } + + [Test] + public void InvalidHexadecimalInteger() + { + // just check that we don't get exceptions: + GenerateLexer(new StringReader("&H")).NextToken(); + // >ulong.MaxValue + GenerateLexer(new StringReader("&hff244636f446c6d58")).NextToken(); + // needs an ulong, but "i" postfix specified integer + GenerateLexer(new StringReader("&hf244636f446c6d58i")).NextToken(); + GenerateLexer(new StringReader("&hf244636f446c6d58ui")).NextToken(); } [Test]