View | Details | Raw Unified | Return to bug 1214327
Collapse All | Expand All

(-)a/src/corelib/serialization/qxmlstream.cpp (-6 / +17 lines)
Lines 1292-1298 inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList() Link Here
1292
    return n;
1292
    return n;
1293
}
1293
}
1294
1294
1295
inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
1295
// Fast scan an XML attribute name (e.g. "xml:lang").
1296
inline QXmlStreamReaderPrivate::FastScanNameResult
1297
QXmlStreamReaderPrivate::fastScanName(Value *val)
1296
{
1298
{
1297
    qsizetype n = 0;
1299
    qsizetype n = 0;
1298
    uint c;
1300
    uint c;
Lines 1300-1306 inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) Link Here
1300
        if (n >= 4096) {
1302
        if (n >= 4096) {
1301
            // This is too long to be a sensible name, and
1303
            // This is too long to be a sensible name, and
1302
            // can exhaust memory, or the range of decltype(*prefix)
1304
            // can exhaust memory, or the range of decltype(*prefix)
1303
            return 0;
1305
            raiseNamePrefixTooLongError();
1306
            return {};
1304
        }
1307
        }
1305
        switch (c) {
1308
        switch (c) {
1306
        case '\n':
1309
        case '\n':
Lines 1334-1351 inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) Link Here
1334
                putChar(':');
1337
                putChar(':');
1335
                --n;
1338
                --n;
1336
            }
1339
            }
1337
            return n;
1340
            return FastScanNameResult(n);
1338
        case ':':
1341
        case ':':
1339
            if (val) {
1342
            if (val) {
1340
                if (val->prefix == 0) {
1343
                if (val->prefix == 0) {
1341
                    val->prefix = qint16(n + 2);
1344
                    val->prefix = qint16(n + 2);
1342
                } else { // only one colon allowed according to the namespace spec.
1345
                } else { // only one colon allowed according to the namespace spec.
1343
                    putChar(c);
1346
                    putChar(c);
1344
                    return n;
1347
                    return FastScanNameResult(n);
1345
                }
1348
                }
1346
            } else {
1349
            } else {
1347
                putChar(c);
1350
                putChar(c);
1348
                return n;
1351
                return FastScanNameResult(n);
1349
            }
1352
            }
1350
            Q_FALLTHROUGH();
1353
            Q_FALLTHROUGH();
1351
        default:
1354
        default:
Lines 1359-1365 inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val) Link Here
1359
    qsizetype pos = textBuffer.size() - n;
1362
    qsizetype pos = textBuffer.size() - n;
1360
    putString(textBuffer, pos);
1363
    putString(textBuffer, pos);
1361
    textBuffer.resize(pos);
1364
    textBuffer.resize(pos);
1362
    return 0;
1365
    return FastScanNameResult(0);
1363
}
1366
}
1364
1367
1365
enum NameChar { NameBeginning, NameNotBeginning, NotName };
1368
enum NameChar { NameBeginning, NameNotBeginning, NotName };
Lines 1839-1844 void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message) Link Here
1839
    raiseError(QXmlStreamReader::NotWellFormedError, message);
1842
    raiseError(QXmlStreamReader::NotWellFormedError, message);
1840
}
1843
}
1841
1844
1845
void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
1846
{
1847
    // TODO: add a ImplementationLimitsExceededError and use it instead
1848
    raiseError(QXmlStreamReader::NotWellFormedError,
1849
               QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
1850
                              "characters)."));
1851
}
1852
1842
void QXmlStreamReaderPrivate::parseError()
1853
void QXmlStreamReaderPrivate::parseError()
1843
{
1854
{
1844
1855
(-)a/src/corelib/serialization/qxmlstream.g (-2 / +10 lines)
Lines 1490-1496 qname ::= LETTER; Link Here
1490
/.
1490
/.
1491
        case $rule_number: {
1491
        case $rule_number: {
1492
            Value &val = sym(1);
1492
            Value &val = sym(1);
1493
            val.len += fastScanName(&val);
1493
            if (auto res = fastScanName(&val))
1494
                val.len += *res;
1495
            else
1496
                return false;
1497
1494
            if (atEnd) {
1498
            if (atEnd) {
1495
                resume($rule_number);
1499
                resume($rule_number);
1496
                return false;
1500
                return false;
Lines 1501-1507 qname ::= LETTER; Link Here
1501
name ::= LETTER;
1505
name ::= LETTER;
1502
/.
1506
/.
1503
        case $rule_number:
1507
        case $rule_number:
1504
            sym(1).len += fastScanName();
1508
            if (auto res = fastScanName())
1509
                sym(1).len += *res;
1510
            else
1511
                return false;
1512
1505
            if (atEnd) {
1513
            if (atEnd) {
1506
                resume($rule_number);
1514
                resume($rule_number);
1507
                return false;
1515
                return false;
(-)a/src/corelib/serialization/qxmlstream_p.h (-2 / +12 lines)
Lines 71-77 public: Link Here
71
71
72
    constexpr XmlStringRef() = default;
72
    constexpr XmlStringRef() = default;
73
    constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
73
    constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
74
        : m_string(string), m_pos(pos), m_size(length)
74
        : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length))
75
    {
75
    {
76
    }
76
    }
77
    XmlStringRef(const QString *string)
77
    XmlStringRef(const QString *string)
Lines 504-510 public: Link Here
504
    qsizetype fastScanLiteralContent();
504
    qsizetype fastScanLiteralContent();
505
    qsizetype fastScanSpace();
505
    qsizetype fastScanSpace();
506
    qsizetype fastScanContentCharList();
506
    qsizetype fastScanContentCharList();
507
    qsizetype fastScanName(Value *val = nullptr);
507
508
    struct FastScanNameResult {
509
        FastScanNameResult() : ok(false) {}
510
        explicit FastScanNameResult(qsizetype len) : addToLen(len), ok(true) { }
511
        operator bool() { return ok; }
512
        qsizetype operator*() { Q_ASSERT(ok); return addToLen; }
513
        qsizetype addToLen;
514
        bool ok;
515
    };
516
    FastScanNameResult fastScanName(Value *val = nullptr);
508
    inline qsizetype fastScanNMTOKEN();
517
    inline qsizetype fastScanNMTOKEN();
509
518
510
519
Lines 513-518 public: Link Here
513
522
514
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
523
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
515
    void raiseWellFormedError(const QString &message);
524
    void raiseWellFormedError(const QString &message);
525
    void raiseNamePrefixTooLongError();
516
526
517
    QXmlStreamEntityResolver *entityResolver;
527
    QXmlStreamEntityResolver *entityResolver;
518
528
(-)a/src/corelib/serialization/qxmlstreamparser_p.h (-2 / +10 lines)
Lines 982-988 bool QXmlStreamReaderPrivate::parse() Link Here
982
982
983
        case 262: {
983
        case 262: {
984
            Value &val = sym(1);
984
            Value &val = sym(1);
985
            val.len += fastScanName(&val);
985
            if (auto res = fastScanName(&val))
986
                val.len += *res;
987
            else
988
                return false;
989
986
            if (atEnd) {
990
            if (atEnd) {
987
                resume(262);
991
                resume(262);
988
                return false;
992
                return false;
Lines 990-996 bool QXmlStreamReaderPrivate::parse() Link Here
990
        } break;
994
        } break;
991
995
992
        case 263:
996
        case 263:
993
            sym(1).len += fastScanName();
997
            if (auto res = fastScanName())
998
                sym(1).len += *res;
999
            else
1000
                return false;
1001
994
            if (atEnd) {
1002
            if (atEnd) {
995
                resume(263);
1003
                resume(263);
996
                return false;
1004
                return false;

Return to bug 1214327