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

(-)a/src/corelib/serialization/qxmlstream.cpp (-14 / +25 lines)
Lines 1302-1316 inline int QXmlStreamReaderPrivate::fastScanContentCharList() Link Here
1302
    return n;
1302
    return n;
1303
}
1303
}
1304
1304
1305
inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
1305
// Fast scan an XML attribute name (e.g. "xml:lang").
1306
inline QXmlStreamReaderPrivate::FastScanNameResult
1307
QXmlStreamReaderPrivate::fastScanName(Value *val)
1306
{
1308
{
1307
    int n = 0;
1309
    int n = 0;
1308
    uint c;
1310
    uint c;
1309
    while ((c = getChar()) != StreamEOF) {
1311
    while ((c = getChar()) != StreamEOF) {
1310
        if (n >= 4096) {
1312
        if (n >= 4096) {
1311
            // This is too long to be a sensible name, and
1313
            // This is too long to be a sensible name, and
1312
            // can exhaust memory
1314
            // can exhaust memory, or the range of decltype(*prefix)
1313
            return 0;
1315
            raiseNamePrefixTooLongError();
1316
            return {};
1314
        }
1317
        }
1315
        switch (c) {
1318
        switch (c) {
1316
        case '\n':
1319
        case '\n':
Lines 1339-1361 inline int QXmlStreamReaderPrivate::fastScanName(int *prefix) Link Here
1339
        case '+':
1342
        case '+':
1340
        case '*':
1343
        case '*':
1341
            putChar(c);
1344
            putChar(c);
1342
            if (prefix && *prefix == n+1) {
1345
            if (val && val->prefix == n + 1) {
1343
                *prefix = 0;
1346
                val->prefix = 0;
1344
                putChar(':');
1347
                putChar(':');
1345
                --n;
1348
                --n;
1346
            }
1349
            }
1347
            return n;
1350
            return FastScanNameResult(n);
1348
        case ':':
1351
        case ':':
1349
            if (prefix) {
1352
            if (val) {
1350
                if (*prefix == 0) {
1353
                if (val->prefix == 0) {
1351
                    *prefix = n+2;
1354
                    val->prefix = n + 2;
1352
                } else { // only one colon allowed according to the namespace spec.
1355
                } else { // only one colon allowed according to the namespace spec.
1353
                    putChar(c);
1356
                    putChar(c);
1354
                    return n;
1357
                    return FastScanNameResult(n);
1355
                }
1358
                }
1356
            } else {
1359
            } else {
1357
                putChar(c);
1360
                putChar(c);
1358
                return n;
1361
                return FastScanNameResult(n);
1359
            }
1362
            }
1360
            Q_FALLTHROUGH();
1363
            Q_FALLTHROUGH();
1361
        default:
1364
        default:
Lines 1364-1375 inline int QXmlStreamReaderPrivate::fastScanName(int *prefix) Link Here
1364
        }
1367
        }
1365
    }
1368
    }
1366
1369
1367
    if (prefix)
1370
    if (val)
1368
        *prefix = 0;
1371
        val->prefix = 0;
1369
    int pos = textBuffer.size() - n;
1372
    int pos = textBuffer.size() - n;
1370
    putString(textBuffer, pos);
1373
    putString(textBuffer, pos);
1371
    textBuffer.resize(pos);
1374
    textBuffer.resize(pos);
1372
    return 0;
1375
    return FastScanNameResult(0);
1373
}
1376
}
1374
1377
1375
enum NameChar { NameBeginning, NameNotBeginning, NotName };
1378
enum NameChar { NameBeginning, NameNotBeginning, NotName };
Lines 1878-1883 void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message) Link Here
1878
    raiseError(QXmlStreamReader::NotWellFormedError, message);
1881
    raiseError(QXmlStreamReader::NotWellFormedError, message);
1879
}
1882
}
1880
1883
1884
void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
1885
{
1886
    // TODO: add a ImplementationLimitsExceededError and use it instead
1887
    raiseError(QXmlStreamReader::NotWellFormedError,
1888
               QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
1889
                              "characters)."));
1890
}
1891
1881
void QXmlStreamReaderPrivate::parseError()
1892
void QXmlStreamReaderPrivate::parseError()
1882
{
1893
{
1883
1894
(-)a/src/corelib/serialization/qxmlstream.g (-3 / +22 lines)
Lines 516-522 public: Link Here
516
    int fastScanLiteralContent();
516
    int fastScanLiteralContent();
517
    int fastScanSpace();
517
    int fastScanSpace();
518
    int fastScanContentCharList();
518
    int fastScanContentCharList();
519
    int fastScanName(int *prefix = nullptr);
519
520
    struct FastScanNameResult {
521
        FastScanNameResult() : ok(false) {}
522
        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
523
        operator bool() { return ok; }
524
        int operator*() { Q_ASSERT(ok); return addToLen; }
525
        int addToLen;
526
        bool ok;
527
    };
528
    FastScanNameResult fastScanName(Value *val = nullptr);
520
    inline int fastScanNMTOKEN();
529
    inline int fastScanNMTOKEN();
521
530
522
531
Lines 525-530 public: Link Here
525
534
526
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
535
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
527
    void raiseWellFormedError(const QString &message);
536
    void raiseWellFormedError(const QString &message);
537
    void raiseNamePrefixTooLongError();
528
538
529
    QXmlStreamEntityResolver *entityResolver;
539
    QXmlStreamEntityResolver *entityResolver;
530
540
Lines 1811-1817 space_opt ::= space; Link Here
1811
qname ::= LETTER;
1821
qname ::= LETTER;
1812
/.
1822
/.
1813
        case $rule_number: {
1823
        case $rule_number: {
1814
            sym(1).len += fastScanName(&sym(1).prefix);
1824
            Value &val = sym(1);
1825
            if (auto res = fastScanName(&val))
1826
                val.len += *res;
1827
            else
1828
                return false;
1829
1815
            if (atEnd) {
1830
            if (atEnd) {
1816
                resume($rule_number);
1831
                resume($rule_number);
1817
                return false;
1832
                return false;
Lines 1822-1828 qname ::= LETTER; Link Here
1822
name ::= LETTER;
1837
name ::= LETTER;
1823
/.
1838
/.
1824
        case $rule_number:
1839
        case $rule_number:
1825
            sym(1).len += fastScanName();
1840
            if (auto res = fastScanName())
1841
                sym(1).len += *res;
1842
            else
1843
                return false;
1844
1826
            if (atEnd) {
1845
            if (atEnd) {
1827
                resume($rule_number);
1846
                resume($rule_number);
1828
                return false;
1847
                return false;
(-)a/src/corelib/serialization/qxmlstream_p.h (-3 / +22 lines)
Lines 1005-1011 public: Link Here
1005
    int fastScanLiteralContent();
1005
    int fastScanLiteralContent();
1006
    int fastScanSpace();
1006
    int fastScanSpace();
1007
    int fastScanContentCharList();
1007
    int fastScanContentCharList();
1008
    int fastScanName(int *prefix = nullptr);
1008
1009
    struct FastScanNameResult {
1010
        FastScanNameResult() : ok(false) {}
1011
        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
1012
        operator bool() { return ok; }
1013
        int operator*() { Q_ASSERT(ok); return addToLen; }
1014
        int addToLen;
1015
        bool ok;
1016
    };
1017
    FastScanNameResult fastScanName(Value *val = nullptr);
1009
    inline int fastScanNMTOKEN();
1018
    inline int fastScanNMTOKEN();
1010
1019
1011
1020
Lines 1014-1019 public: Link Here
1014
1023
1015
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
1024
    void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
1016
    void raiseWellFormedError(const QString &message);
1025
    void raiseWellFormedError(const QString &message);
1026
    void raiseNamePrefixTooLongError();
1017
1027
1018
    QXmlStreamEntityResolver *entityResolver;
1028
    QXmlStreamEntityResolver *entityResolver;
1019
1029
Lines 1939-1945 bool QXmlStreamReaderPrivate::parse() Link Here
1939
        break;
1949
        break;
1940
1950
1941
        case 262: {
1951
        case 262: {
1942
            sym(1).len += fastScanName(&sym(1).prefix);
1952
            Value &val = sym(1);
1953
            if (auto res = fastScanName(&val))
1954
                val.len += *res;
1955
            else
1956
                return false;
1957
1943
            if (atEnd) {
1958
            if (atEnd) {
1944
                resume(262);
1959
                resume(262);
1945
                return false;
1960
                return false;
Lines 1947-1953 bool QXmlStreamReaderPrivate::parse() Link Here
1947
        } break;
1962
        } break;
1948
1963
1949
        case 263:
1964
        case 263:
1950
            sym(1).len += fastScanName();
1965
            if (auto res = fastScanName())
1966
                sym(1).len += *res;
1967
            else
1968
                return false;
1969
1951
            if (atEnd) {
1970
            if (atEnd) {
1952
                resume(263);
1971
                resume(263);
1953
                return false;
1972
                return false;

Return to bug 1214327