Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package cppcheck for openSUSE:Factory 
checked in at 2023-12-21 23:38:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cppcheck (Old)
 and      /work/SRC/openSUSE:Factory/.cppcheck.new.1840 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "cppcheck"

Thu Dec 21 23:38:44 2023 rev:36 rq:1134347 version:2.12.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/cppcheck/cppcheck.changes        2023-11-13 
22:24:51.316304785 +0100
+++ /work/SRC/openSUSE:Factory/.cppcheck.new.1840/cppcheck.changes      
2023-12-21 23:38:56.403252835 +0100
@@ -1,0 +2,5 @@
+Wed Dec 20 23:14:07 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- add CVE-2023-39070.patch (CVE-2023-39070, bsc#1215233)
+
+-------------------------------------------------------------------

New:
----
  CVE-2023-39070.patch

BETA DEBUG BEGIN:
  New:
- add CVE-2023-39070.patch (CVE-2023-39070, bsc#1215233)
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ cppcheck.spec ++++++
--- /var/tmp/diff_new_pack.TJRq6M/_old  2023-12-21 23:38:57.131279420 +0100
+++ /var/tmp/diff_new_pack.TJRq6M/_new  2023-12-21 23:38:57.135279565 +0100
@@ -25,6 +25,7 @@
 Source:         
https://github.com/danmar/cppcheck/archive/refs/tags/%{version}.tar.gz#/%{name}-%{version}.tar.gz
 Patch0:         eb076d87.patch
 Patch1:         werror-return-type.patch
+Patch2:         CVE-2023-39070.patch
 BuildRequires:  cmake
 BuildRequires:  docbook-xsl-stylesheets
 BuildRequires:  fdupes

++++++ CVE-2023-39070.patch ++++++
>From 76695f6be2685a1ee7436e563bc550eab506952a Mon Sep 17 00:00:00 2001
From: Dirk Mueller <dmuel...@suse.com>
Date: Tue, 19 Dec 2023 20:44:22 +0100
Subject: [PATCH] Fix #12272 (removeContradiction() Avoid use-after-free on
 multiple remove) (#5707)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

As reported in
https://sourceforge.net/p/cppcheck/discussion/general/thread/fa43fb8ab1/
removeContradiction() minValue/maxValue.remove(..) can access free'd
memory as it removes all matching values by iterating over the complete
list. Creating a full copy instead of a reference avoids this issue.

Signed-off-by: Dirk Müller <d...@dmllr.de>
---
 lib/preprocessor.cpp | 16 +++++++-----
 lib/token.cpp        | 60 +++++++++++++++++++++++---------------------
 2 files changed, 42 insertions(+), 34 deletions(-)

Index: cppcheck-2.12.1/lib/token.cpp
===================================================================
--- cppcheck-2.12.1.orig/lib/token.cpp
+++ cppcheck-2.12.1/lib/token.cpp
@@ -1955,64 +1955,68 @@ static bool isAdjacent(const ValueFlow::
     return std::abs(x.intvalue - y.intvalue) == 1;
 }
 
-static bool removePointValue(std::list<ValueFlow::Value>& values, 
ValueFlow::Value& x)
+static bool removePointValue(std::list<ValueFlow::Value>& values, 
std::list<ValueFlow::Value>::iterator& x)
 {
-    const bool isPoint = x.bound == ValueFlow::Value::Bound::Point;
+    const bool isPoint = x->bound == ValueFlow::Value::Bound::Point;
     if (!isPoint)
-        x.decreaseRange();
+        x->decreaseRange();
     else
-        values.remove(x);
+        x = values.erase(x);
     return isPoint;
 }
 
 static bool removeContradiction(std::list<ValueFlow::Value>& values)
 {
     bool result = false;
-    for (ValueFlow::Value& x : values) {
-        if (x.isNonValue())
+    for (auto itx = values.begin(); itx != values.end(); ++itx) {
+        if (itx->isNonValue())
             continue;
-        for (ValueFlow::Value& y : values) {
-            if (y.isNonValue())
+
+        auto ity = itx;
+        ++ity;
+        for (; ity != values.end(); ++ity) {
+            if (ity->isNonValue())
                 continue;
-            if (x == y)
+            if (*itx == *ity)
                 continue;
-            if (x.valueType != y.valueType)
+            if (itx->valueType != ity->valueType)
                 continue;
-            if (x.isImpossible() == y.isImpossible())
+            if (itx->isImpossible() == ity->isImpossible())
                 continue;
-            if (x.isSymbolicValue() && 
!ValueFlow::Value::sameToken(x.tokvalue, y.tokvalue))
+            if (itx->isSymbolicValue() && 
!ValueFlow::Value::sameToken(itx->tokvalue, ity->tokvalue))
                 continue;
-            if (!x.equalValue(y)) {
-                auto compare = [](const ValueFlow::Value& x, const 
ValueFlow::Value& y) {
-                    return x.compareValue(y, less{});
+            if (!itx->equalValue(*ity)) {
+                auto compare = [](const 
std::list<ValueFlow::Value>::const_iterator& x, const 
std::list<ValueFlow::Value>::const_iterator& y) {
+                    return x->compareValue(*y, less{});
                 };
-                const ValueFlow::Value& maxValue = std::max(x, y, compare);
-                const ValueFlow::Value& minValue = std::min(x, y, compare);
+                auto itMax = std::max(itx, ity, compare);
+                auto itMin = std::min(itx, ity, compare);
                 // TODO: Adjust non-points instead of removing them
-                if (maxValue.isImpossible() && maxValue.bound == 
ValueFlow::Value::Bound::Upper) {
-                    values.remove(minValue);
+                if (itMax->isImpossible() && itMax->bound == 
ValueFlow::Value::Bound::Upper) {
+                    values.erase(itMin);
                     return true;
                 }
-                if (minValue.isImpossible() && minValue.bound == 
ValueFlow::Value::Bound::Lower) {
-                    values.remove(maxValue);
+                if (itMin->isImpossible() && itMin->bound == 
ValueFlow::Value::Bound::Lower) {
+                    values.erase(itMax);
                     return true;
                 }
                 continue;
             }
-            const bool removex = !x.isImpossible() || y.isKnown();
-            const bool removey = !y.isImpossible() || x.isKnown();
-            if (x.bound == y.bound) {
+            const bool removex = !itx->isImpossible() || ity->isKnown();
+            const bool removey = !ity->isImpossible() || itx->isKnown();
+            if (itx->bound == ity->bound) {
                 if (removex)
-                    values.remove(x);
+                    values.erase(itx);
                 if (removey)
-                    values.remove(y);
+                    values.erase(ity);
+                // itx and ity are invalidated
                 return true;
             }
             result = removex || removey;
             bool bail = false;
-            if (removex && removePointValue(values, x))
+            if (removex && removePointValue(values, itx))
                 bail = true;
-            if (removey && removePointValue(values, y))
+            if (removey && removePointValue(values, ity))
                 bail = true;
             if (bail)
                 return true;

Reply via email to