From 4cc0d3719eccdc657dfd019382ba4324cf6ad664 Mon Sep 17 00:00:00 2001
From: Marc Mutz <marc.mutz@qt.io>
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).

Manual conflict resolution for 6.8:
- rebased to before conflicting change
  a41c860c7dacfb6b785e0a24a4c3f26c3cde3c20 (6.9). Kept the std::pair
  of the cherry-pick source, as QPair is just a template alias
- rebased to before conflicting change
  6cab6872feeeb2521d67ead9a54fee8d038c8dc4 (6.11) by keeping the
  static keyword instead of the inline one from the cherry-pick
  source

Pick-to: 6.5
Coverity-Id: 911179
Change-Id: Ida3185a4aa9cf953c6b52840c6fdedac6257ef5b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 623cbf2a071b1709377ba841e47b52cc472c5dfc)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit a21dbdb96974cf94419eedad5684128c7973604f)
(cherry picked from commit 52bdba5baf7e7df4e20949541bd24479d1ef5787)
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
---

diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index b90cddb..c52d3a4 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -374,20 +374,20 @@
 }
 
 // ### move this to qnetworkcookie_p.h and share with qnetworkaccesshttpbackend
-static QPair<QByteArray, QByteArray> nextField(QByteArrayView text, int &position, bool isNameValue)
+static std::pair<QByteArray, QByteArray> 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 qMakePair(QByteArray(), QByteArray()); //'=' is required for name-value-pair (RFC6265 section 5.2, rule 2)
@@ -396,7 +396,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();
 
@@ -956,8 +956,8 @@
     QList<QNetworkCookie> 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;
 
@@ -978,7 +978,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 5315c04..1da7fcd 100644
--- a/src/network/access/qnetworkcookie_p.h
+++ b/src/network/access/qnetworkcookie_p.h
@@ -44,7 +44,7 @@
     return c == ' ' || c == '\t' || c == '\r' || c == '\n';
 }
 
-static int nextNonWhitespace(QByteArrayView text, int from)
+static 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 c9714ed..f1bef78 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -51,7 +51,7 @@
     // value-directive = token "=" (token | quoted-string)
     QHash<QByteArray, QByteArray> 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
