forked from pool/cppcheck
Accepting request 1134958 from home:mathletic:branches:devel:tools
- update to 2.13.0 * newCheck passedByValueCallback for functions which take a parameter by value but are used as callbacks * newCheck returnImplicitInt for C functions without return type * newCheck iterateByValue for iterating by value in a range-based for loop when a const reference could be used - Drop patches werror-return-type.patch, eb076d87.patch, and CVE-2023-39070.patch which are part of upstream or fixed in a similar way. OBS-URL: https://build.opensuse.org/request/show/1134958 OBS-URL: https://build.opensuse.org/package/show/devel:tools/cppcheck?expand=0&rev=122
This commit is contained in:
parent
f2ba187ef3
commit
c62715bad4
@ -1,122 +0,0 @@
|
|||||||
From 76695f6be2685a1ee7436e563bc550eab506952a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dirk Mueller <dmueller@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 <dirk@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;
|
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:2a3d4ba1179419612183ab3d6aed6d3b18be75e98cd6f138ea8e2020905dced2
|
|
||||||
size 3579702
|
|
3
cppcheck-2.13.0.tar.gz
Normal file
3
cppcheck-2.13.0.tar.gz
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8229afe1dddc3ed893248b8a723b428dc221ea014fbc76e6289840857c03d450
|
||||||
|
size 3643744
|
@ -1,3 +1,16 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Sun Dec 24 06:43:54 UTC 2023 - Christoph G <foss@grueninger.de>
|
||||||
|
|
||||||
|
- update to 2.13.0
|
||||||
|
* newCheck passedByValueCallback for functions which take a
|
||||||
|
parameter by value but are used as callbacks
|
||||||
|
* newCheck returnImplicitInt for C functions without return type
|
||||||
|
* newCheck iterateByValue for iterating by value in a range-based
|
||||||
|
for loop when a const reference could be used
|
||||||
|
- Drop patches werror-return-type.patch, eb076d87.patch, and
|
||||||
|
CVE-2023-39070.patch which are part of upstream or fixed in a
|
||||||
|
similar way.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Dec 20 23:14:07 UTC 2023 - Dirk Müller <dmueller@suse.com>
|
Wed Dec 20 23:14:07 UTC 2023 - Dirk Müller <dmueller@suse.com>
|
||||||
|
|
||||||
|
@ -17,15 +17,12 @@
|
|||||||
|
|
||||||
|
|
||||||
Name: cppcheck
|
Name: cppcheck
|
||||||
Version: 2.12.1
|
Version: 2.13.0
|
||||||
Release: 0
|
Release: 0
|
||||||
Summary: A tool for static C/C++ code analysis
|
Summary: A tool for static C/C++ code analysis
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
URL: https://github.com/danmar/cppcheck
|
URL: https://github.com/danmar/cppcheck
|
||||||
Source: https://github.com/danmar/cppcheck/archive/refs/tags/%{version}.tar.gz#/%{name}-%{version}.tar.gz
|
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: cmake
|
||||||
BuildRequires: docbook-xsl-stylesheets
|
BuildRequires: docbook-xsl-stylesheets
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
From eb076d877b48c09d5c34cad27b001d18971fde3f Mon Sep 17 00:00:00 2001
|
|
||||||
From: moui0 <69300707+moui0@users.noreply.github.com>
|
|
||||||
Date: Sun, 8 Oct 2023 05:04:57 +0800
|
|
||||||
Subject: [PATCH] Improve testcases for unsigned char platforms (#5524)
|
|
||||||
|
|
||||||
I got error messages while building `cppcheck 2.12.0` for RISC-V Arch
|
|
||||||
Linux:
|
|
||||||
```
|
|
||||||
Testing Complete
|
|
||||||
Number of tests: 4420
|
|
||||||
Number of todos: 331
|
|
||||||
Tests failed: 2
|
|
||||||
|
|
||||||
/usr/src/debug/cppcheck/cppcheck/test/testcondition.cpp:4501(TestCondition::alwaysTrue): Assertion failed.
|
|
||||||
Expected:
|
|
||||||
[test.cpp:6]: (style) Condition 'o[1]=='\0'' is always false\n
|
|
||||||
|
|
||||||
Actual:
|
|
||||||
[test.cpp:4] -> [test.cpp:6]: (style) Condition 'o[1]=='\0'' is always false\n
|
|
||||||
|
|
||||||
_____
|
|
||||||
/usr/src/debug/cppcheck/cppcheck/test/testcondition.cpp:5014(TestCondition::alwaysTrueContainer): Assertion failed.
|
|
||||||
Expected:
|
|
||||||
[test.cpp:5]: (style) Condition 'buffer.back()=='\0'' is always false\n
|
|
||||||
|
|
||||||
Actual:
|
|
||||||
[test.cpp:3] -> [test.cpp:5]: (style) Condition 'buffer.back()=='\0'' is always false\n
|
|
||||||
```
|
|
||||||
|
|
||||||
I found out the reason is that the testcases were designed for
|
|
||||||
x86/x86_64 or other `signed char` platforms (i.e. default character type
|
|
||||||
is `signed char` ), whereareas RISC-V is an `unsigned char` platform,
|
|
||||||
which causes different behavior in
|
|
||||||
`lib/valueflow.cpp:valueFlowImpossibleValues`. I'm not sure whether this
|
|
||||||
error leads from a functional bug, so if you have a better approach to
|
|
||||||
fix it, please let me know.
|
|
||||||
|
|
||||||
Maybe you could reproduce this error on x86_64 platform by setting
|
|
||||||
`defaultSign = 'u';` in `Platform::set(Type t)`.
|
|
||||||
---
|
|
||||||
test/testcondition.cpp | 12 ++++++++++--
|
|
||||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/test/testcondition.cpp b/test/testcondition.cpp
|
|
||||||
index bfe9713fce3..ae9dfdb7a61 100644
|
|
||||||
--- a/test/testcondition.cpp
|
|
||||||
+++ b/test/testcondition.cpp
|
|
||||||
@@ -4498,7 +4498,11 @@ class TestCondition : public TestFixture {
|
|
||||||
" if (o[1] == '\\0') {}\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n");
|
|
||||||
- ASSERT_EQUALS("[test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout.str());
|
|
||||||
+ if (std::numeric_limits<char>::is_signed) {
|
|
||||||
+ ASSERT_EQUALS("[test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout.str());
|
|
||||||
+ } else {
|
|
||||||
+ ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (style) Condition 'o[1]=='\\0'' is always false\n", errout.str());
|
|
||||||
+ }
|
|
||||||
|
|
||||||
check("void f(int x) {\n" // #11449
|
|
||||||
" int i = x;\n"
|
|
||||||
@@ -5016,7 +5020,11 @@ class TestCondition : public TestFixture {
|
|
||||||
" buffer.back() == '\\n' ||\n"
|
|
||||||
" buffer.back() == '\\0') {}\n"
|
|
||||||
"}\n");
|
|
||||||
- ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'buffer.back()=='\\0'' is always false\n", errout.str());
|
|
||||||
+ if (std::numeric_limits<char>::is_signed) {
|
|
||||||
+ ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'buffer.back()=='\\0'' is always false\n", errout.str());
|
|
||||||
+ } else {
|
|
||||||
+ ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Condition 'buffer.back()=='\\0'' is always false\n", errout.str());
|
|
||||||
+ }
|
|
||||||
|
|
||||||
// #9353
|
|
||||||
check("typedef struct { std::string s; } X;\n"
|
|
@ -1,35 +0,0 @@
|
|||||||
Index: cppcheck-2.12.0/lib/keywords.cpp
|
|
||||||
===================================================================
|
|
||||||
--- cppcheck-2.12.0.orig/lib/keywords.cpp
|
|
||||||
+++ cppcheck-2.12.0/lib/keywords.cpp
|
|
||||||
@@ -165,6 +166,7 @@ const std::unordered_set<std::string>& K
|
|
||||||
return c23_keywords_all;*/
|
|
||||||
}
|
|
||||||
assert(false && "unreachable");
|
|
||||||
+ __builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cppcheck-suppress unusedFunction
|
|
||||||
@@ -185,6 +187,7 @@ const std::unordered_set<std::string>& K
|
|
||||||
return cpp23_keywords_all;
|
|
||||||
}
|
|
||||||
assert(false && "unreachable");
|
|
||||||
+ __builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cppcheck-suppress unusedFunction
|
|
||||||
@@ -202,6 +205,7 @@ const std::unordered_set<std::string>& K
|
|
||||||
return c23_keywords_all;*/
|
|
||||||
}
|
|
||||||
assert(false && "unreachable");
|
|
||||||
+ __builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// cppcheck-suppress unusedFunction
|
|
||||||
@@ -223,5 +227,6 @@ const std::unordered_set<std::string>& K
|
|
||||||
return cpp23_keywords;
|
|
||||||
}
|
|
||||||
assert(false && "unreachable");
|
|
||||||
+ __builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user