diff options
author | Thiago Macieira <[email protected]> | 2024-04-18 07:55:59 -0700 |
---|---|---|
committer | Thiago Macieira <[email protected]> | 2024-04-21 06:48:11 -0700 |
commit | f0f2a9ef2600288b16b69c135389dfe1fea89a8d (patch) | |
tree | d68cdeafa81e19ad90edfda42b12046ff8092a2d | |
parent | 8ef89c1c01c79de404d6bb0abe9072fb1438e2b1 (diff) |
QString: ensure multi-arg arg() parses replacement like single-arg arg()
There was a discrepancy that the multi-arg arg() overload would accept
any number of digits in the placeholder, resolving up to value 999
(e.g., %000001 was interpreted as placeholder #1), but the single-arg
arg() overload only supported exactly one or two digits. The single-arg
behavior was documented, so use it.
[ChangeLog][Important Behavior Changes] The QString::arg() overload
taking multiple QString-like arguments is now fixed to interpret
placeholders like the other arg() overloads: it will find at most two
digits after the '%' character. That is, the sequence "%123" is now
interpreted as placeholder #12 followed by character '3' (verbatim).
Pick-to: 6.7
Fixes: QTBUG-118581
Change-Id: I455fe22ef4ad4b2f9b01fffd17c767a948d41138
Reviewed-by: Ahmad Samir <[email protected]>
-rw-r--r-- | src/corelib/text/qstring.cpp | 19 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 12 |
2 files changed, 18 insertions, 13 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index fe9790403fe..f0bf0c50a30 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -9077,7 +9077,7 @@ static inline char16_t to_unicode(const QChar c) { return c.unicode(); } static inline char16_t to_unicode(const char c) { return QLatin1Char{c}.unicode(); } template <typename Char> -static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumber = 999) +static int getEscape(const Char *uc, qsizetype *pos, qsizetype len) { qsizetype i = *pos; ++i; @@ -9088,17 +9088,16 @@ static int getEscape(const Char *uc, qsizetype *pos, qsizetype len, int maxNumbe if (uint(escape) >= 10U) return -1; ++i; - while (i < len) { + if (i < len) { + // there's a second digit int digit = to_unicode(uc[i]) - '0'; - if (uint(digit) >= 10U) - break; - escape = (escape * 10) + digit; - ++i; - } - if (escape <= maxNumber) { - *pos = i; - return escape; + if (uint(digit) < 10U) { + escape = (escape * 10) + digit; + ++i; + } } + *pos = i; + return escape; } return -1; } diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 35bddf16a43..d56a9ebd20b 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -6721,9 +6721,15 @@ void tst_QString::arg() str = str.arg(u"ahoy"_s, u"there"_s); QCOMPARE(str, "one 2 3 4 5 6 7 8 9 foo ahoy there bar"_L1); - QString str2(u"%123 %234 %345 %456 %567 %999 %1000 %1230"_s); - str2 = str2.arg(u"A"_s, u"B"_s, u"C"_s, u"D"_s, u"E"_s, u"F"_s); - QCOMPARE(str2, QLatin1String("A B C D E F %1000 %1230")); + // Make sure the single- and multi-arg expand the same sequences: at most + // two digits. The sequence below has four replacements: %01, %10 (twice), + // %11, and %12. + QString str2 = u"%100 %101 %110 %12 %0100"_s; + QLatin1StringView str2expected = "B0 B1 C0 D A00"_L1; + QCOMPARE(str2.arg(QChar(u'A')).arg(QChar(u'B')).arg(QChar(u'C')).arg(QChar(u'D')), str2expected); + QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B')).arg(QChar(u'C')).arg(QChar(u'D')), str2expected); + QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B'), QChar(u'C')).arg(QChar(u'D')), str2expected); + QCOMPARE(str2.arg(QChar(u'A'), QChar(u'B'), QChar(u'C'), QChar(u'D')), str2expected); QCOMPARE(u"%1"_s.arg(-1, 3, 10, QChar(u'0')), "-01"_L1); QCOMPARE(u"%1"_s.arg(-100, 3, 10, QChar(u'0')), "-100"_L1); |