From f2ba187ef366cac44e09bcf7f6e18780931e9c516170ab213d5490eb830afc43 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Wed, 20 Dec 2023 23:14:38 +0000 Subject: [PATCH] - add CVE-2023-39070.patch (CVE-2023-39070, bsc#1215233) OBS-URL: https://build.opensuse.org/package/show/devel:tools/cppcheck?expand=0&rev=120 --- CVE-2023-39070.patch | 122 +++++++++++++++++++++++++++++++++++++++++++ cppcheck.changes | 5 ++ cppcheck.spec | 1 + 3 files changed, 128 insertions(+) create mode 100644 CVE-2023-39070.patch diff --git a/CVE-2023-39070.patch b/CVE-2023-39070.patch new file mode 100644 index 0000000..27dd297 --- /dev/null +++ b/CVE-2023-39070.patch @@ -0,0 +1,122 @@ +From 76695f6be2685a1ee7436e563bc550eab506952a Mon Sep 17 00:00:00 2001 +From: Dirk Mueller +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 +--- + 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& values, ValueFlow::Value& x) ++static bool removePointValue(std::list& values, std::list::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& 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::const_iterator& x, const std::list::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; diff --git a/cppcheck.changes b/cppcheck.changes index f2408af..10c3c20 100644 --- a/cppcheck.changes +++ b/cppcheck.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Wed Dec 20 23:14:07 UTC 2023 - Dirk Müller + +- add CVE-2023-39070.patch (CVE-2023-39070, bsc#1215233) + ------------------------------------------------------------------- Thu Nov 9 10:21:24 UTC 2023 - Guillaume GARDET diff --git a/cppcheck.spec b/cppcheck.spec index 41baa75..8e4150c 100644 --- a/cppcheck.spec +++ b/cppcheck.spec @@ -25,6 +25,7 @@ URL: https://github.com/danmar/cppcheck 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