Address Coverity defect about buffer overrun

Coverity warned that chunk could be >= tldChunkCount (2), and
tldData[chunk] (array of length 2) would be accessed out of bounds.

This can not happen, but it was unclear.
Clarify logic with comments and asserts, that Coverity will hopefully
understand now.

Change-Id: I2a38c685cfcbc69ed123918e8cbed360b20b1035
Coverity-Id: 178254
Pick-to: 5.15
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Dimitrios Apostolou 2020-05-19 19:47:10 +02:00
parent d4d08e009d
commit bc58e0dc7a

View File

@ -58,6 +58,8 @@ enum TLDMatchType {
ExceptionMatch, ExceptionMatch,
}; };
// Scan the auto-generated table of TLDs for an entry. For more details
// see comments in file: util/corelib/qurl-generateTLDs/main.cpp
static bool containsTLDEntry(QStringView entry, TLDMatchType match) static bool containsTLDEntry(QStringView entry, TLDMatchType match)
{ {
const QStringView matchSymbols[] = { const QStringView matchSymbols[] = {
@ -66,18 +68,36 @@ static bool containsTLDEntry(QStringView entry, TLDMatchType match)
u"!", u"!",
}; };
const auto symbol = matchSymbols[match]; const auto symbol = matchSymbols[match];
int index = qt_hash(entry, qt_hash(symbol)) % tldCount; const int index = qt_hash(entry, qt_hash(symbol)) % tldCount;
// select the right chunk from the big table // select the right chunk from the big table
short chunk = 0; short chunk = 0;
uint chunkIndex = tldIndices[index], offset = 0; uint chunkIndex = tldIndices[index], offset = 0;
while (chunk < tldChunkCount && tldIndices[index] >= tldChunks[chunk]) {
// The offset in the big string, of the group that our entry hashes into.
const auto tldGroupOffset = tldIndices[index];
// It should always be inside all chunks' total size.
Q_ASSERT(tldGroupOffset < tldChunks[tldChunkCount - 1]);
// All offsets are stored in non-decreasing order.
// This check is within bounds as tldIndices has length tldCount+1.
Q_ASSERT(tldGroupOffset <= tldIndices[index + 1]);
// The last extra entry in tldIndices
// should be equal to the total of all chunks' lengths.
Q_ASSERT(tldIndices[tldCount] == tldChunks[tldChunkCount - 1]);
// Find which chunk contains the tldGroupOffset
while (tldGroupOffset >= tldChunks[chunk]) {
chunkIndex -= tldChunks[chunk]; chunkIndex -= tldChunks[chunk];
offset += tldChunks[chunk]; offset += tldChunks[chunk];
chunk++; chunk++;
// We can not go above the number of chunks we have, since all our
// indices are less than the total chunks' size (see asserts above).
Q_ASSERT(chunk < tldChunkCount);
} }
// check all the entries from the given index // check all the entries from the given offset
while (chunkIndex < tldIndices[index+1] - offset) { while (chunkIndex < tldIndices[index+1] - offset) {
const auto utf8 = tldData[chunk] + chunkIndex; const auto utf8 = tldData[chunk] + chunkIndex;
if ((symbol.isEmpty() || QLatin1Char(*utf8) == symbol) && entry == QString::fromUtf8(utf8 + symbol.size())) if ((symbol.isEmpty() || QLatin1Char(*utf8) == symbol) && entry == QString::fromUtf8(utf8 + symbol.size()))