Skip to content

Commit

Permalink
Merge branch 'main' into chr_Fix12186
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Nov 16, 2023
2 parents ad9e541 + e473000 commit ffaa861
Show file tree
Hide file tree
Showing 22 changed files with 1,954 additions and 1,849 deletions.
3 changes: 2 additions & 1 deletion addons/misra.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@ def get_function_pointer_type(tok):
ret += '('
tok = tok.next.next
while tok and (tok.str not in '()'):
ret += ' ' + tok.str
if tok.varId is None:
ret += ' ' + tok.str
tok = tok.next
if (tok is None) or tok.str != ')':
return None
Expand Down
7 changes: 7 additions & 0 deletions addons/test/misra/misra-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,13 @@ static void misra_10_8(u8 x, s32 a, s32 b) {
int (*misra_11_1_p)(void); // 8.4
void *misra_11_1_bad1 = (void*)misra_11_1_p; // 11.1 8.4

// #12172
typedef void (*pfFunc_11_1)(uint32_t some);
extern pfFunc_11_1 data_11_1[10];
void func_11_1(pfFunc_11_1 ptr){ //8.4
data_11_1[index] = ptr; // no-warning
}

struct misra_11_2_s;
struct misra_11_2_t;

Expand Down
60 changes: 31 additions & 29 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,42 +72,44 @@
#include <windows.h>
#endif

class XMLErrorMessagesLogger : public ErrorLogger
{
void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override
{
std::cout << outmsg << std::endl;
}

void reportErr(const ErrorMessage &msg) override
namespace {
class XMLErrorMessagesLogger : public ErrorLogger
{
reportOut(msg.toXML());
}
void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override
{
std::cout << outmsg << std::endl;
}

void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override
{}
};
void reportErr(const ErrorMessage &msg) override
{
reportOut(msg.toXML());
}

class CmdLineLoggerStd : public CmdLineLogger
{
public:
CmdLineLoggerStd() = default;
void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override
{}
};

void printMessage(const std::string &message) override
class CmdLineLoggerStd : public CmdLineLogger
{
printRaw("cppcheck: " + message);
}
public:
CmdLineLoggerStd() = default;

void printError(const std::string &message) override
{
printMessage("error: " + message);
}
void printMessage(const std::string &message) override
{
printRaw("cppcheck: " + message);
}

void printRaw(const std::string &message) override
{
std::cout << message << std::endl;
}
};
void printError(const std::string &message) override
{
printMessage("error: " + message);
}

void printRaw(const std::string &message) override
{
std::cout << message << std::endl;
}
};
}

class CppCheckExecutor::StdLogger : public ErrorLogger
{
Expand Down
84 changes: 43 additions & 41 deletions cli/processexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,59 +68,61 @@ ProcessExecutor::ProcessExecutor(const std::list<std::pair<std::string, std::siz
assert(mSettings.jobs > 1);
}

class PipeWriter : public ErrorLogger {
public:
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', CHILD_END='5'};
namespace {
class PipeWriter : public ErrorLogger {
public:
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', CHILD_END='5'};

explicit PipeWriter(int pipe) : mWpipe(pipe) {}
explicit PipeWriter(int pipe) : mWpipe(pipe) {}

void reportOut(const std::string &outmsg, Color c) override {
writeToPipe(REPORT_OUT, static_cast<char>(c) + outmsg);
}

void reportErr(const ErrorMessage &msg) override {
writeToPipe(REPORT_ERROR, msg.serialize());
}

void writeEnd(const std::string& str) const {
writeToPipe(CHILD_END, str);
}
void reportOut(const std::string &outmsg, Color c) override {
writeToPipe(REPORT_OUT, static_cast<char>(c) + outmsg);
}

private:
// TODO: how to log file name in error?
void writeToPipeInternal(PipeSignal type, const void* data, std::size_t to_write) const
{
const ssize_t bytes_written = write(mWpipe, data, to_write);
if (bytes_written <= 0) {
const int err = errno;
std::cerr << "#### ThreadExecutor::writeToPipeInternal() error for type " << type << ": " << std::strerror(err) << std::endl;
std::exit(EXIT_FAILURE);
void reportErr(const ErrorMessage &msg) override {
writeToPipe(REPORT_ERROR, msg.serialize());
}
// TODO: write until everything is written
if (bytes_written != to_write) {
std::cerr << "#### ThreadExecutor::writeToPipeInternal() error for type " << type << ": insufficient data written (expected: " << to_write << " / got: " << bytes_written << ")" << std::endl;
std::exit(EXIT_FAILURE);

void writeEnd(const std::string& str) const {
writeToPipe(CHILD_END, str);
}
}

void writeToPipe(PipeSignal type, const std::string &data) const
{
private:
// TODO: how to log file name in error?
void writeToPipeInternal(PipeSignal type, const void* data, std::size_t to_write) const
{
const char t = static_cast<char>(type);
writeToPipeInternal(type, &t, 1);
const ssize_t bytes_written = write(mWpipe, data, to_write);
if (bytes_written <= 0) {
const int err = errno;
std::cerr << "#### ThreadExecutor::writeToPipeInternal() error for type " << type << ": " << std::strerror(err) << std::endl;
std::exit(EXIT_FAILURE);
}
// TODO: write until everything is written
if (bytes_written != to_write) {
std::cerr << "#### ThreadExecutor::writeToPipeInternal() error for type " << type << ": insufficient data written (expected: " << to_write << " / got: " << bytes_written << ")" << std::endl;
std::exit(EXIT_FAILURE);
}
}

const unsigned int len = static_cast<unsigned int>(data.length());
void writeToPipe(PipeSignal type, const std::string &data) const
{
static constexpr std::size_t l_size = sizeof(unsigned int);
writeToPipeInternal(type, &len, l_size);
}
{
const char t = static_cast<char>(type);
writeToPipeInternal(type, &t, 1);
}

writeToPipeInternal(type, data.c_str(), len);
}
const unsigned int len = static_cast<unsigned int>(data.length());
{
static constexpr std::size_t l_size = sizeof(unsigned int);
writeToPipeInternal(type, &len, l_size);
}

const int mWpipe;
};
writeToPipeInternal(type, data.c_str(), len);
}

const int mWpipe;
};
}

bool ProcessExecutor::handleRead(int rpipe, unsigned int &result, const std::string& filename)
{
Expand Down
26 changes: 14 additions & 12 deletions gui/librarydialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,20 @@ class QWidget;

// TODO: get/compare functions from header

class FunctionListItem : public QListWidgetItem {
public:
FunctionListItem(QListWidget *view,
CppcheckLibraryData::Function *function,
bool selected)
: QListWidgetItem(view), function(function) {
setText(function->name);
setFlags(flags() | Qt::ItemIsEditable);
setSelected(selected);
}
CppcheckLibraryData::Function *function;
};
namespace {
class FunctionListItem : public QListWidgetItem {
public:
FunctionListItem(QListWidget *view,
CppcheckLibraryData::Function *function,
bool selected)
: QListWidgetItem(view), function(function) {
setText(function->name);
setFlags(flags() | Qt::ItemIsEditable);
setSelected(selected);
}
CppcheckLibraryData::Function *function;
};
}

LibraryDialog::LibraryDialog(QWidget *parent) :
QDialog(parent),
Expand Down
44 changes: 23 additions & 21 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2943,27 +2943,29 @@ static const Token* findExpressionChangedImpl(const Token* expr,
return result;
}

struct ExpressionChangedSimpleFind {
template<class F>
const Token* operator()(const Token* start, const Token* end, F f) const
{
return findToken(start, end, f);
}
};

struct ExpressionChangedSkipDeadCode {
const Library* library;
const std::function<std::vector<MathLib::bigint>(const Token* tok)>* evaluate;
ExpressionChangedSkipDeadCode(const Library* library,
const std::function<std::vector<MathLib::bigint>(const Token* tok)>& evaluate)
: library(library), evaluate(&evaluate)
{}
template<class F>
const Token* operator()(const Token* start, const Token* end, F f) const
{
return findTokenSkipDeadCode(library, start, end, f, *evaluate);
}
};
namespace {
struct ExpressionChangedSimpleFind {
template<class F>
const Token* operator()(const Token* start, const Token* end, F f) const
{
return findToken(start, end, f);
}
};

struct ExpressionChangedSkipDeadCode {
const Library* library;
const std::function<std::vector<MathLib::bigint>(const Token* tok)>* evaluate;
ExpressionChangedSkipDeadCode(const Library* library,
const std::function<std::vector<MathLib::bigint>(const Token* tok)>& evaluate)
: library(library), evaluate(&evaluate)
{}
template<class F>
const Token* operator()(const Token* start, const Token* end, F f) const
{
return findTokenSkipDeadCode(library, start, end, f, *evaluate);
}
};
}

const Token* findExpressionChanged(const Token* expr,
const Token* start,
Expand Down
24 changes: 12 additions & 12 deletions lib/checkio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,19 @@ static OpenMode getMode(const std::string& str)
return OpenMode::UNKNOWN_OM;
}

struct Filepointer {
OpenMode mode;
nonneg int mode_indent{};
enum class Operation {NONE, UNIMPORTANT, READ, WRITE, POSITIONING, OPEN, CLOSE, UNKNOWN_OP} lastOperation = Operation::NONE;
nonneg int op_indent{};
enum class AppendMode { UNKNOWN_AM, APPEND, APPEND_EX };
AppendMode append_mode = AppendMode::UNKNOWN_AM;
std::string filename;
explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM)
: mode(mode_) {}
};

namespace {
struct Filepointer {
OpenMode mode;
nonneg int mode_indent{};
enum class Operation {NONE, UNIMPORTANT, READ, WRITE, POSITIONING, OPEN, CLOSE, UNKNOWN_OP} lastOperation = Operation::NONE;
nonneg int op_indent{};
enum class AppendMode { UNKNOWN_AM, APPEND, APPEND_EX };
AppendMode append_mode = AppendMode::UNKNOWN_AM;
std::string filename;
explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM)
: mode(mode_) {}
};

const std::unordered_set<std::string> whitelist = { "clearerr", "feof", "ferror", "fgetpos", "ftell", "setbuf", "setvbuf", "ungetc", "ungetwc" };
}

Expand Down
18 changes: 10 additions & 8 deletions lib/checkleakautovar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void VarInfo::print()
std::string strusage;
const auto use = possibleUsage.find(it->first);
if (use != possibleUsage.end())
strusage = use->second.first;
strusage = use->second.first->str();

std::string status;
switch (it->second.status) {
Expand Down Expand Up @@ -140,7 +140,7 @@ void VarInfo::print()
}
}

void VarInfo::possibleUsageAll(const std::pair<std::string, Usage>& functionUsage)
void VarInfo::possibleUsageAll(const std::pair<const Token*, Usage>& functionUsage)
{
possibleUsage.clear();
for (std::map<int, AllocInfo>::const_iterator it = alloctype.cbegin(); it != alloctype.cend(); ++it)
Expand Down Expand Up @@ -176,13 +176,15 @@ void CheckLeakAutoVar::deallocReturnError(const Token *tok, const Token *dealloc
reportError(locations, Severity::error, "deallocret", "$symbol:" + varname + "\nReturning/dereferencing '$symbol' after it is deallocated / released", CWE672, Certainty::normal);
}

void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair<std::string, VarInfo::Usage>& functionUsage)
void CheckLeakAutoVar::configurationInfo(const Token* tok, const std::pair<const Token*, VarInfo::Usage>& functionUsage)
{
if (mSettings->checkLibrary && functionUsage.second == VarInfo::USED) {
if (mSettings->checkLibrary && functionUsage.second == VarInfo::USED &&
(!functionUsage.first || !functionUsage.first->function() || !functionUsage.first->function()->hasBody())) {
const std::string funcStr = functionUsage.first ? mSettings->library.getFunctionName(functionUsage.first) : "f";
reportError(tok,
Severity::information,
"checkLibraryUseIgnore",
"--check-library: Function " + functionUsage.first + "() should have <use>/<leak-ignore> configuration");
"--check-library: Function " + funcStr + "() should have <use>/<leak-ignore> configuration");
}
}

Expand Down Expand Up @@ -684,7 +686,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
if (allocation.status == VarInfo::NOALLOC && Token::simpleMatch(tok, ") ; }")) {
if (ftok->isKeyword())
continue;
const std::string functionName(mSettings->library.getFunctionName(ftok));
bool unknown = false;
if (mTokenizer->isScopeNoReturn(tok->tokAt(2), &unknown)) {
if (!unknown)
Expand All @@ -693,9 +694,10 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
if (ftok->function() && !ftok->function()->isAttributeNoreturn() &&
!(ftok->function()->functionScope && mTokenizer->isScopeNoReturn(ftok->function()->functionScope->bodyEnd))) // check function scope
continue;
const std::string functionName(mSettings->library.getFunctionName(ftok));
if (!mSettings->library.isLeakIgnore(functionName) && !mSettings->library.isUse(functionName)) {
const VarInfo::Usage usage = Token::simpleMatch(openingPar, "( )") ? VarInfo::NORET : VarInfo::USED; // TODO: check parameters passed to function
varInfo.possibleUsageAll({ functionName, usage });
varInfo.possibleUsageAll({ ftok, usage });
}
}
}
Expand Down Expand Up @@ -895,7 +897,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
if (var != alloctype.end()) {
if (allocation.status == VarInfo::NOALLOC) {
// possible usage
varInfo.possibleUsage[arg->varId()] = { tok->str(), VarInfo::USED };
varInfo.possibleUsage[arg->varId()] = { tok, VarInfo::USED };
if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&")
varInfo.erase(arg->varId());
} else if (var->second.managed()) {
Expand Down
Loading

0 comments on commit ffaa861

Please sign in to comment.