From 52bdba5baf7e7df4e20949541bd24479d1ef5787 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 13 Jul 2026 10:01:16 +0200 Subject: [PATCH] QtNetwork: port nextNonWhitespace() and all its users to qsizetype Coverity complained that QNetworkReplyHttpImpl's parseHttpOptionHeader() could overflow. It showed a 51-step trace, which I didn't bother to follow. It's pretty clear that the use of int here narrows from the qizetype used by QByteArray, so all kinds of things can go wrong, incl. that the if (pos == header.size()) can never trigger, if header.size() > INT_MAX. So port nextNonWhitespace() from int to qsizetype and ditto all its callers. As a drive-by, mark some variables const (the functions are long...), and replace the re-use of `comma` with a narrowly-scoped, shadowing use to avoid having to leave `comma` non-const. Amends the port of QByteArray to qsizetype (6.0). Pick-to: 6.8 6.5 Coverity-Id: 911179 Change-Id: Ida3185a4aa9cf953c6b52840c6fdedac6257ef5b Reviewed-by: Thiago Macieira (cherry picked from commit 623cbf2a071b1709377ba841e47b52cc472c5dfc) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit a21dbdb96974cf94419eedad5684128c7973604f) --- diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 6c44e42..6f20518 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -376,20 +376,20 @@ } // ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend -static std::pair nextField(QByteArrayView text, int &position, bool isNameValue) +static std::pair nextField(QByteArrayView text, qsizetype &position, bool isNameValue) { // format is one of: // (1) token // (2) token = token // (3) token = quoted-string - const int length = text.size(); + const qsizetype length = text.size(); position = nextNonWhitespace(text, position); - int semiColonPosition = text.indexOf(';', position); + qsizetype semiColonPosition = text.indexOf(';', position); if (semiColonPosition < 0) semiColonPosition = length; //no ';' means take everything to end of string - int equalsPosition = text.indexOf('=', position); + qsizetype equalsPosition = text.indexOf('=', position); if (equalsPosition < 0 || equalsPosition > semiColonPosition) { if (isNameValue) return std::pair(QByteArray(), QByteArray()); //'=' is required for name-value-pair (RFC6265 section 5.2, rule 2) @@ -398,7 +398,7 @@ QByteArray first = text.mid(position, equalsPosition - position).trimmed().toByteArray(); QByteArray second; - int secondLength = semiColonPosition - equalsPosition - 1; + qsizetype secondLength = semiColonPosition - equalsPosition - 1; if (secondLength > 0) second = text.mid(equalsPosition + 1, secondLength).trimmed().toByteArray(); @@ -958,8 +958,8 @@ QList result; const QDateTime now = QDateTime::currentDateTimeUtc(); - int position = 0; - const int length = cookieString.size(); + qsizetype position = 0; + const qsizetype length = cookieString.size(); while (position < length) { QNetworkCookie cookie; @@ -980,7 +980,7 @@ if (field.first.compare("expires", Qt::CaseInsensitive) == 0) { position -= field.second.size(); - int end; + qsizetype end; for (end = position; end < length; ++end) if (isValueSeparator(cookieString.at(end))) break; diff --git a/src/network/access/qnetworkcookie_p.h b/src/network/access/qnetworkcookie_p.h index b768727..40cad6d 100644 --- a/src/network/access/qnetworkcookie_p.h +++ b/src/network/access/qnetworkcookie_p.h @@ -46,7 +46,7 @@ } // Used in qnetworkcookie.cpp and qnetworkreplyhttpimpl.cpp -inline int nextNonWhitespace(QByteArrayView text, int from) +inline qsizetype nextNonWhitespace(QByteArrayView text, qsizetype from) { // RFC 2616 defines linear whitespace as: // LWS = [CRLF] 1*( SP | HT ) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 798364b..f841942 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -51,7 +51,7 @@ // value-directive = token "=" (token | quoted-string) QHash result; - int pos = 0; + qsizetype pos = 0; while (true) { // skip spaces pos = nextNonWhitespace(header, pos); @@ -59,15 +59,15 @@ return result; // end of parsing // pos points to a non-whitespace - int comma = header.indexOf(',', pos); - int equal = header.indexOf('=', pos); + const qsizetype comma = header.indexOf(',', pos); + const qsizetype equal = header.indexOf('=', pos); if (comma == pos || equal == pos) // huh? Broken header. return result; // The key name is delimited by either a comma, an equal sign or the end // of the header, whichever comes first - int end = comma; + qsizetype end = comma; if (end == -1) end = header.size(); if (equal != -1 && end > equal) @@ -75,7 +75,7 @@ const auto key = header.sliced(pos, end - pos).trimmed(); pos = end + 1; - if (uint(equal) < uint(comma)) { + if (size_t(equal) < size_t(comma)) { // case: token "=" (token | quoted-string) // skip spaces pos = nextNonWhitespace(header, pos); @@ -126,10 +126,10 @@ result.insert(key.toByteArray().toLower(), value); // find the comma now: - comma = header.indexOf(',', pos); - if (comma == -1) + if (qsizetype comma = header.indexOf(',', pos); comma == -1) return result; // end of parsing - pos = comma + 1; + else + pos = comma + 1; } else { // case: token // key is already set