Sophie

Sophie

distrib > Mageia > cauldron > x86_64 > media > core-release-src > by-pkgid > 4c532bfb9916518564da5ba2805999f5 > files > 103

qtbase5-5.15.12-3.mga10.src.rpm

From 82937a2b7b5afc0915f27531e64d3d0331cd4a6b Mon Sep 17 00:00:00 2001
From: Marc Mutz <marc.mutz@qt.io>
Date: Wed, 5 Jul 2023 08:36:06 +0200
Subject: [PATCH 104/147] Make sure we don't count down past 0
 QT_FATAL_CRITICALS
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The old code first checked for == 0, then, if false, executed a
fetchAndAdd(-1), both with relaxed memory ordering. This can lead to
executions that, counter to what the code comment states, can count
down past 0:

    // T1                   T2
    loadRelaxed()                                  // true
                            loadRelaxed()          // true
    fetchAndAddRelaxed(-1)                         // e.g. 1 → 0
                            fetchAndAddRelaxed(-1) // 0 → -1

while fatality is detected exactly once, this execution doesn't stop
at 0 and causes further calls to isFatal() to count down further, with
the (very) remote spectre of underflow past INT_MIN.

Fix by using a CAS loop instead, so each count-down uses only one
step, not two, which therefore can no longer interleave.

Fixes: QTBUG-115062
Pick-to: 6.6 6.5 6.2 5.15
Change-Id: If77b906c94cb4b9fa91bfad84fe63bc8d9103b0a
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit b933a5668cc5647d26378f8a9a52901d0497585d)
---
 src/corelib/global/qlogging.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 8510cf3a26..0f253d4a27 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -193,7 +193,11 @@ static bool is_fatal_count_down(QAtomicInt &n)
 {
     // it's fatal if the current value is exactly 1,
     // otherwise decrement if it's non-zero
-    return n.loadRelaxed() && n.fetchAndAddRelaxed(-1) == 1;
+
+    int v = n.loadRelaxed();
+    while (v != 0 && !n.testAndSetRelaxed(v, v - 1, v))
+        ;
+    return v == 1; // we exited the loop, so either v == 0 or CAS succeeded to set n from v to v-1
 }
 
 static bool isFatal(QtMsgType msgType)
-- 
2.40.1