Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/checkers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ namespace checkers {
{"CheckSizeof::sizeofVoid","portability"},
{"CheckSizeof::sizeofsizeof","warning"},
{"CheckSizeof::suspiciousSizeofCalculation","warning,inconclusive"},
{"CheckStl::algorithmOutOfBounds",""},
{"CheckStl::checkDereferenceInvalidIterator","warning"},
{"CheckStl::checkDereferenceInvalidIterator2",""},
{"CheckStl::checkFindInsert","performance"},
Expand Down
407 changes: 392 additions & 15 deletions lib/checkstl.cpp

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions lib/checkstl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "checkimpl.h"
#include "config.h"
#include "errortypes.h"
#include "mathlib.h"

#include <cstdint>
#include <string>
Expand Down Expand Up @@ -73,6 +74,7 @@ class CPPCHECKLIB CheckStl : public Check {
"- useless calls of string and STL functions\n"
"- dereferencing an invalid iterator\n"
"- erasing an iterator that is out of bounds\n"
"- out of bounds access of an iterator passed to an STL algorithm\n"
"- reading from empty STL container\n"
"- iterating over an empty STL container\n"
"- consider using an STL algorithm instead of raw loop\n"
Expand Down Expand Up @@ -183,6 +185,12 @@ class CPPCHECKLIB CheckStlImpl : public CheckImpl {

void eraseIteratorOutOfBounds();

/**
* Check that the iterator given to an STL algorithm is not accessed
* out of bounds: std::equal(in.begin(), in.end(), out.begin())
*/
void algorithmOutOfBounds();

void checkMutexes();

bool isContainerSize(const Token *containerToken, const Token *expr) const;
Expand Down Expand Up @@ -235,6 +243,14 @@ class CPPCHECKLIB CheckStlImpl : public CheckImpl {

void eraseIteratorOutOfBoundsError(const Token* ftok, const Token* itertok, const ValueFlow::Value* val = nullptr);

void algorithmOutOfBoundsError(const Token* tok,
const std::string& algoName,
MathLib::bigint accessed,
MathLib::bigint available,
const ValueFlow::Value* value,
bool mayAccessFewer,
bool inconclusive);

void globalLockGuardError(const Token *tok);
void localMutexError(const Token *tok);
};
Expand Down
12 changes: 12 additions & 0 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3844,12 +3844,24 @@ static void valueFlowForwardConst(Token* start,
{
if (!precedes(start, end))
throw InternalError(var->nameToken(), "valueFlowForwardConst: start token does not precede the end token.");
const bool hasContainerSizeValue = std::any_of(values.begin(), values.end(), [](const ValueFlow::Value& value) {
return value.isContainerSizeValue();
});
for (Token* tok = start; tok != end; tok = tok->next()) {
if (tok->varId() == var->declarationId()) {
for (const ValueFlow::Value& value : values)
setTokenValue(tok, value, settings);
} else {
[&] {
// Add the container size to iterators of the container (mirrors ContainerExpressionAnalyzer::match)
if (hasContainerSizeValue && astIsIterator(tok) && isAliasOf(tok, var->declarationId())) {
for (const ValueFlow::Value& value : values) {
if (!value.isContainerSizeValue())
continue;
setTokenValue(tok, value, settings);
}
return;
}
// Follow references
const auto& refs = tok->refs();
auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
Expand Down
9 changes: 4 additions & 5 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# python -m pytest test-other.py

import os
Expand Down Expand Up @@ -4429,25 +4428,25 @@ def __test_active_checkers(tmp_path, active_cnt, total_cnt, use_misra=False, use


def test_active_unusedfunction_only(tmp_path):
__test_active_checkers(tmp_path, 1, 187, use_unusedfunction_only=True)
__test_active_checkers(tmp_path, 1, 188, use_unusedfunction_only=True)


def test_active_unusedfunction_only_builddir(tmp_path):
checkers_exp = [
'CheckUnusedFunctions::check'
]
__test_active_checkers(tmp_path, 1, 187, use_unusedfunction_only=True, checkers_exp=checkers_exp)
__test_active_checkers(tmp_path, 1, 188, use_unusedfunction_only=True, checkers_exp=checkers_exp)


def test_active_unusedfunction_only_misra(tmp_path):
__test_active_checkers(tmp_path, 1, 387, use_unusedfunction_only=True, use_misra=True)
__test_active_checkers(tmp_path, 1, 388, use_unusedfunction_only=True, use_misra=True)


def test_active_unusedfunction_only_misra_builddir(tmp_path):
checkers_exp = [
'CheckUnusedFunctions::check'
]
__test_active_checkers(tmp_path, 1, 387, use_unusedfunction_only=True, use_misra=True, checkers_exp=checkers_exp)
__test_active_checkers(tmp_path, 1, 388, use_unusedfunction_only=True, use_misra=True, checkers_exp=checkers_exp)


def test_analyzerinfo(tmp_path):
Expand Down
Loading
Loading