diff options
7 files changed, 55 insertions, 24 deletions
diff --git a/src/qml/qml/parser/qqmljslexer.cpp b/src/qml/qml/parser/qqmljslexer.cpp index edd85ec878..0df49279e2 100644 --- a/src/qml/qml/parser/qqmljslexer.cpp +++ b/src/qml/qml/parser/qqmljslexer.cpp @@ -54,7 +54,7 @@ QT_END_NAMESPACE using namespace QQmlJS; -static int regExpFlagFromChar(const QChar &ch) +static inline int regExpFlagFromChar(const QChar &ch) { switch (ch.unicode()) { case 'g': return Lexer::RegExp_Global; @@ -64,7 +64,7 @@ static int regExpFlagFromChar(const QChar &ch) return 0; } -static unsigned char convertHex(ushort c) +static inline unsigned char convertHex(ushort c) { if (c >= '0' && c <= '9') return (c - '0'); @@ -74,12 +74,12 @@ static unsigned char convertHex(ushort c) return (c - 'A' + 10); } -static QChar convertHex(QChar c1, QChar c2) +static inline QChar convertHex(QChar c1, QChar c2) { return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } -static QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) +static inline QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) { return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()), (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); @@ -329,6 +329,27 @@ QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok) return QChar(); } +QChar Lexer::decodeHexEscapeCharacter(bool *ok) +{ + if (isHexDigit(_codePtr[0]) && isHexDigit(_codePtr[1])) { + scanChar(); + + const QChar c1 = _char; + scanChar(); + + const QChar c2 = _char; + scanChar(); + + if (ok) + *ok = true; + + return convertHex(c1, c2); + } + + *ok = false; + return QChar(); +} + static inline bool isIdentifierStart(QChar ch) { // fast path for ascii @@ -705,35 +726,29 @@ again: scanChar(); QChar u; - bool ok = false; switch (_char.unicode()) { // unicode escape sequence - case 'u': + case 'u': { + bool ok = false; u = decodeUnicodeEscapeCharacter(&ok); if (! ok) { _errorCode = IllegalUnicodeEscapeSequence; _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal unicode escape sequence"); return T_ERROR; } - break; + } break; // hex escape sequence - case 'x': - if (isHexDigit(_codePtr[0]) && isHexDigit(_codePtr[1])) { - scanChar(); - - const QChar c1 = _char; - scanChar(); - - const QChar c2 = _char; - scanChar(); - - u = convertHex(c1, c2); - } else { - u = _char; + case 'x': { + bool ok = false; + u = decodeHexEscapeCharacter(&ok); + if (!ok) { + _errorCode = IllegalHexadecimalEscapeSequence; + _errorMessage = QCoreApplication::translate("QQmlParser", "Illegal hexadecimal escape sequence"); + return T_ERROR; } - break; + } break; // single character escape sequence case '\\': u = QLatin1Char('\\'); scanChar(); break; diff --git a/src/qml/qml/parser/qqmljslexer_p.h b/src/qml/qml/parser/qqmljslexer_p.h index e1b51da92b..23af61d650 100644 --- a/src/qml/qml/parser/qqmljslexer_p.h +++ b/src/qml/qml/parser/qqmljslexer_p.h @@ -128,7 +128,8 @@ public: IllegalUnicodeEscapeSequence, UnclosedComment, IllegalExponentIndicator, - IllegalIdentifier + IllegalIdentifier, + IllegalHexadecimalEscapeSequence }; enum RegExpBodyPrefix { @@ -203,6 +204,7 @@ private: void syncProhibitAutomaticSemicolon(); QChar decodeUnicodeEscapeCharacter(bool *ok); + QChar decodeHexEscapeCharacter(bool *ok); private: Engine *_engine; diff --git a/tests/auto/qml/parserstress/tests/ecma/LexicalConventions/7.7.4.js b/tests/auto/qml/parserstress/tests/ecma/LexicalConventions/7.7.4.js index 4a3173db6c..4b799f8df1 100644 --- a/tests/auto/qml/parserstress/tests/ecma/LexicalConventions/7.7.4.js +++ b/tests/auto/qml/parserstress/tests/ecma/LexicalConventions/7.7.4.js @@ -135,9 +135,10 @@ new TestCase( SECTION, "\\x1E1", String.fromCharCode(30)+"1", "\x1E new TestCase( SECTION, "\\x0F0", String.fromCharCode(15)+"0", "\x0F0" ); // G is out of hex range - +/* Invalid testcase: we no longer silently ignore invalid hexadecimal escape sequences. new TestCase( SECTION, "\\xG", "xG", "\xG" ); new TestCase( SECTION, "\\xCG", "xCG", "\xCG" ); +*/ // DoubleStringCharacter::EscapeSequence::CharacterEscapeSequence::\ NonEscapeCharacter new TestCase( SECTION, "\\a", "a", "\a" ); diff --git a/tests/auto/qml/parserstress/tests/ecma_2/RegExp/hex-001.js b/tests/auto/qml/parserstress/tests/ecma_2/RegExp/hex-001.js index 3e85ac7abf..f2dccd9267 100644 --- a/tests/auto/qml/parserstress/tests/ecma_2/RegExp/hex-001.js +++ b/tests/auto/qml/parserstress/tests/ecma_2/RegExp/hex-001.js @@ -55,7 +55,10 @@ startTest(); AddRegExpCases( new RegExp("\x41"), "new RegExp('\\x41')", "A", "A", 1, 0, ["A"] ); AddRegExpCases( new RegExp("\x412"),"new RegExp('\\x412')", "A2", "A2", 1, 0, ["A2"] ); + +/* Invalid testcase: we no longer silently ignore invalid hexadecimal escape sequences. AddRegExpCases( new RegExp("\x1g"), "new RegExp('\\x1g')", "x1g","x1g", 1, 0, ["x1g"] ); +*/ AddRegExpCases( new RegExp("A"), "new RegExp('A')", "\x41", "\\x41", 1, 0, ["A"] ); AddRegExpCases( new RegExp("A"), "new RegExp('A')", "\x412", "\\x412", 1, 0, ["A"] ); diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index 2957a70d04..65549efddc 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -126,6 +126,7 @@ void tst_qmlmin::initTestCase() invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.3.qml"; invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.4.qml"; invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.5.qml"; + invalidFiles << "tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml"; invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.1.qml"; invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.2.qml"; } diff --git a/tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml b/tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml new file mode 100644 index 0000000000..8ee5b59d9e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/stringParsing_error.6.qml @@ -0,0 +1,9 @@ + +import QtQuick 2.0 + +QtObject { + function code() { + "\x0G" + } +} + diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index d022e9dedc..06590f0ad6 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -7383,7 +7383,7 @@ void tst_qqmlecmascript::numberParsing() void tst_qqmlecmascript::stringParsing() { - for (int i = 1; i < 6; ++i) { + for (int i = 1; i < 7; ++i) { QString file("stringParsing_error.%1.qml"); file = file.arg(i); QQmlComponent component(&engine, testFileUrl(file)); |