Skip to content

Commit 42d8fed

Browse files
committed
use configuration
1 parent 4d43009 commit 42d8fed

File tree

2 files changed

+39
-52
lines changed

2 files changed

+39
-52
lines changed

lib/checkleakautovar.cpp

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -363,52 +363,40 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
363363
while (Token::Match(ftok, "%name% :: %name%"))
364364
ftok = ftok->tokAt(2);
365365

366-
// memcpy / memmove
367-
if (Token::Match(varTok, "memcpy|memmove")) {
368-
const std::vector<const Token*> args = getArguments(varTok);
369-
// too few args for memcpy / memmove call
370-
if (args.size() < 3)
371-
continue;
372-
const Token *dst = args[0];
373-
const Token *src = args[1];
374-
375-
// check that dst arg is pointer to pointer
376-
int dstIndirectionLevel = 0;
377-
while (dst->str() == "*") {
378-
dst = dst->astOperand1();
379-
dstIndirectionLevel--;
380-
}
381-
if (dst->str() == "&") {
382-
dst = dst->astOperand1();
383-
dstIndirectionLevel++;
384-
}
385-
if (!dst->isVariable())
386-
continue;
387-
if (dstIndirectionLevel + dst->variable()->valueType()->pointer != 2)
388-
continue;
389-
390-
// check that src arg is pointer to pointer
391-
int srcIndirectionLevel = 0;
392-
while (src->str() == "*") {
393-
src = src->astOperand1();
394-
srcIndirectionLevel--;
395-
}
396-
if (src->str() == "&") {
397-
src = src->astOperand1();
398-
srcIndirectionLevel++;
366+
if (const Library::Function *libFunc = mSettings->library.getFunction(ftok)) {
367+
using ArgumentChecks = Library::ArgumentChecks;
368+
using Direction = ArgumentChecks::Direction;
369+
const std::vector<const Token *> args = getArguments(ftok);
370+
const std::map<int, ArgumentChecks> &argChecks = libFunc->argumentChecks;
371+
bool hasOutParam = false;
372+
for (const auto &pair : argChecks) {
373+
hasOutParam |= std::any_of(pair.second.direction.cbegin(), pair.second.direction.cend(), [&](const Direction dir) {
374+
return dir == Direction::DIR_OUT;
375+
});
376+
if (hasOutParam)
377+
break;
399378
}
400-
if (!src->isVariable())
401-
continue;
402-
if (srcIndirectionLevel + src->variable()->valueType()->pointer != 2)
403-
continue;
404-
405-
if (!dst->variable()->isArgument()) {
406-
varInfo.alloctype[dst->varId()].status = VarInfo::AllocStatus::ALLOC;
379+
if (hasOutParam) {
380+
for (int i = 0; i < args.size(); i++) {
381+
if (!argChecks.count(i + 1))
382+
continue;
383+
const ArgumentChecks argCheck = argChecks.at(i + 1);
384+
bool isInParam = std::any_of(argCheck.direction.cbegin(), argCheck.direction.cend(), [&](const Direction dir) {
385+
return dir == Direction::DIR_IN;
386+
});
387+
if (!isInParam)
388+
continue;
389+
const Token *varTok = args[i];
390+
int indirect = 0;
391+
while (varTok->isUnaryOp("&")) {
392+
varTok = varTok->astOperand1();
393+
indirect++;
394+
}
395+
if (varTok->isVariable() && indirect) {
396+
varInfo.erase(varTok->varId());
397+
}
398+
}
407399
}
408-
409-
// no multivariable checking currently (see assignment below)
410-
// treat source pointer as unallocated
411-
varInfo.erase(src->varId());
412400
}
413401

414402
auto isAssignment = [](const Token* varTok) -> const Token* {

test/testleakautovar.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class TestLeakAutoVar : public TestFixture {
6464
TEST_CASE(assign25);
6565
TEST_CASE(assign26);
6666

67-
TEST_CASE(memcpyWithPtr1); // #11542
68-
TEST_CASE(memcpyWithPtr2);
67+
TEST_CASE(memcpy1); // #11542
68+
TEST_CASE(memcpy2);
6969

7070
TEST_CASE(isAutoDealloc);
7171

@@ -636,7 +636,7 @@ class TestLeakAutoVar : public TestFixture {
636636
ASSERT_EQUALS("", errout_str());
637637
}
638638

639-
void memcpyWithPtr1() { // #11542
639+
void memcpy1() { // #11542
640640
const Settings s = settingsBuilder().library("std.cfg").library("posix.cfg").build();
641641
check("void f(char** old, char* value) {\n"
642642
" char *str = strdup(value);\n"
@@ -645,14 +645,13 @@ class TestLeakAutoVar : public TestFixture {
645645
ASSERT_EQUALS("", errout_str());
646646
}
647647

648-
void memcpyWithPtr2() {
648+
void memcpy2() {
649649
const Settings s = settingsBuilder().library("std.cfg").library("posix.cfg").build();
650-
check("void f(char* value) {\n"
651-
" char *old = NULL;\n"
650+
check("void f(char* old, char* value, size_t len) {\n"
652651
" char *str = strdup(value);\n"
653-
" memcpy(&old, &str, sizeof(char*));\n"
652+
" memcpy(old, str, len);\n"
654653
"}\n", &s);
655-
ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: old\n", errout_str());
654+
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: str\n", errout_str());
656655
}
657656

658657
void isAutoDealloc() {

0 commit comments

Comments
 (0)