From 714579401f8287e80264e50e1c5c1ba41ea9dd24 Mon Sep 17 00:00:00 2001 From: Alexander Mai Date: Sat, 21 Nov 2015 22:35:58 +0100 Subject: [PATCH] #7160 Internal error: Unhandled char constant '\1'. Correct MathLib::toLongNumber. Create new utility function MathLib::characterLiteralToLongNumber --- lib/mathlib.cpp | 116 ++++++++++++++++++++++++++----------------- lib/mathlib.h | 3 ++ test/testmathlib.cpp | 8 +++ 3 files changed, 82 insertions(+), 45 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 50e8528ce..a4419a36a 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -313,6 +313,76 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return ret; } + +MathLib::bigint MathLib::characterLiteralToLongNumber(const std::string& str) +{ + if (str.size()==1) + return str[0] & 0xff; + if (str[0] != '\\') + throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant " + str); + + if (str[1]=='x') { + return toLongNumber("0x" + str.substr(2)); + } + char c; + switch (str.size()-1) { + case 1: + switch (str[1]) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + return str[1]-'0'; + case 'a': + c = '\a'; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = '\v'; + break; + case '\\': + case '\?': + case '\'': + case '\"': + c = str[1]; + break; + default: + throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant " + str); + break; + } + return c & 0xff; + case 2: + if (isOctalDigit(str[1]) && isOctalDigit(str[2])) + return toLongNumber("0" + str.substr(1)); + break; + case 3: + if (isOctalDigit(str[1]) && isOctalDigit(str[2]) && isOctalDigit(str[3])) + return toLongNumber("0" + str.substr(1)); + break; + } + + throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant " + str); +} + + MathLib::bigint MathLib::toLongNumber(const std::string & str) { // hexadecimal numbers: @@ -364,51 +434,7 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) } if (str[0] == '\'' && str.size() >= 3U && str[str.size()-1U] == '\'') { - char c; - if (str.size() == 3U) - c = str[1]; - else if (str[1] == '\\' && str.size() == 4U) { - switch (str[2]) { - case '0': - c = '\0'; - break; - case 'a': - c = '\a'; - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case '\\': - case '\?': - case '\'': - case '\"': - c = str[2]; - break; - default: - throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant " + str); - } - } else if (str[1] == '\\' && str[2] == '0' && str.size() == 6U) { - return toLongNumber(str.substr(2,3)); - } else if (str[1] == '\\' && str[2] == 'x' && str.size() == 6U) { - return toLongNumber("0" + str.substr(2,3)); - } else - throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant " + str); - return c & 0xff; + return characterLiteralToLongNumber(str.substr(1,str.size()-2)); } bigint ret = 0; diff --git a/lib/mathlib.h b/lib/mathlib.h index c0ab3b3ab..683e60b19 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -113,6 +113,9 @@ public: * @return true if given character is octal digit. */ static bool isOctalDigit(char c); +private: + static MathLib::bigint characterLiteralToLongNumber(const std::string& str); + }; MathLib::value operator+(const MathLib::value &v1, const MathLib::value &v2); diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index a35e5553a..5d0cce793 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -271,9 +271,17 @@ private: // from char ASSERT_EQUALS((int)('A'), MathLib::toLongNumber("'A'")); + ASSERT_EQUALS((int)('\0'), MathLib::toLongNumber("'\\0'")); ASSERT_EQUALS((int)('\r'), MathLib::toLongNumber("'\\r'")); ASSERT_EQUALS((int)('\x12'), MathLib::toLongNumber("'\\x12'")); + // may cause some compile problems: ASSERT_EQUALS((int)('\x123'), MathLib::toLongNumber("'\\x123'")); + // may cause some compile problems: ASSERT_EQUALS((int)('\x1234'), MathLib::toLongNumber("'\\x1234'")); + ASSERT_EQUALS((int)('\3'), MathLib::toLongNumber("'\\3'")); + ASSERT_EQUALS((int)('\34'), MathLib::toLongNumber("'\\34'")); ASSERT_EQUALS((int)('\034'), MathLib::toLongNumber("'\\034'")); + ASSERT_EQUALS((int)('\134'), MathLib::toLongNumber("'\\134'")); + ASSERT_THROW(MathLib::toLongNumber("'\\9'"), InternalError); + ASSERT_THROW(MathLib::toLongNumber("'\\934'"), InternalError); ASSERT_EQUALS(-8552249625308161526, MathLib::toLongNumber("0x89504e470d0a1a0a")); ASSERT_EQUALS(-8481036456200365558, MathLib::toLongNumber("0x8a4d4e470d0a1a0a"));