QRegularExpression: do not assume QStringViews are NUL terminated

The convenience API used to look up the index of a named capturing
group expects NUL terminated strings. Therefore, we can't just
use it together with QStringViews, which may be not. Use the
non-convenience API instead.

Pick-to: 5.15
Change-Id: I25ca14de49b13ee1764525f8b19f2550c30c1afa
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Giuseppe D'Angelo 2020-08-24 11:45:23 +02:00
parent acbf9a858b
commit 049d8892ea
2 changed files with 49 additions and 3 deletions

View File

@ -1040,9 +1040,24 @@ int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
if (!compiledPattern)
return -1;
int index = pcre2_substring_number_from_name_16(compiledPattern, reinterpret_cast<PCRE2_SPTR16>(name.utf16()));
if (index >= 0)
return index;
// See the other usages of pcre2_pattern_info_16 for more details about this
PCRE2_SPTR16 *namedCapturingTable;
unsigned int namedCapturingTableEntryCount;
unsigned int namedCapturingTableEntrySize;
pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
const auto currentNamedCapturingTableRow =
reinterpret_cast<const char16_t *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
if (name == (currentNamedCapturingTableRow + 1)) {
const int index = *currentNamedCapturingTableRow;
return index;
}
}
return -1;
}

View File

@ -69,6 +69,7 @@ private slots:
void captureCount();
void captureNames_data();
void captureNames();
void captureNamesNul();
void pcreJitStackUsage_data();
void pcreJitStackUsage();
void regularExpressionMatch_data();
@ -1620,6 +1621,36 @@ void tst_QRegularExpression::captureNames()
}
void tst_QRegularExpression::captureNamesNul()
{
QRegularExpression re("a(\\d+)b(?<name>\\d+)c(?<anotherName>\\d+)d(\\d+)e$");
QVERIFY(re.isValid());
QCOMPARE(re.captureCount(), 4);
QStringList namedCaptureGroups = re.namedCaptureGroups();
QCOMPARE(namedCaptureGroups[0], QString());
QCOMPARE(namedCaptureGroups[1], QString());
QCOMPARE(namedCaptureGroups[2], "name");
QCOMPARE(namedCaptureGroups[3], "anotherName");
QCOMPARE(namedCaptureGroups[4], QString());
QRegularExpressionMatch m = re.match("a12b456c789d0e");
QVERIFY(m.hasMatch());
QString captureName("name");
QCOMPARE(m.captured(captureName), "456");
QCOMPARE(m.captured(QStringView(captureName)), "456");
QCOMPARE(m.captured(qToStringViewIgnoringNull(captureName)), "456");
QCOMPARE(m.captured(u"name"), "456");
captureName = "anotherName";
QCOMPARE(m.captured(captureName), "789");
QCOMPARE(m.captured(QStringView(captureName)), "789");
QCOMPARE(m.captured(qToStringViewIgnoringNull(captureName)), "789");
QCOMPARE(m.captured(u"anotherName"), "789");
}
void tst_QRegularExpression::pcreJitStackUsage_data()
{
QTest::addColumn<QString>("pattern");