Skip to content

Commit ac8e981

Browse files
committed
Fix #11300 FP accessMoved with write access (inconclusive)
1 parent db9f970 commit ac8e981

7 files changed

Lines changed: 35 additions & 14 deletions

File tree

cfg/std.cfg

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3993,7 +3993,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
39933993
<noreturn>false</noreturn>
39943994
<leak-ignore/>
39953995
<not-overlapping-data ptr1-arg="1" ptr2-arg="2" size-arg="3"/>
3996-
<arg nr="1" direction="out">
3996+
<arg nr="1" direction="out" indirect="1">
39973997
<not-null/>
39983998
<minsize type="argvalue" arg="3"/>
39993999
</arg>
@@ -4100,7 +4100,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
41004100
<returnValue type="errno_t"/>
41014101
<noreturn>false</noreturn>
41024102
<leak-ignore/>
4103-
<arg nr="1" direction="out">
4103+
<arg nr="1" direction="out" indirect="1">
41044104
<not-null/>
41054105
<minsize type="argvalue" arg="2"/>
41064106
</arg>
@@ -4121,7 +4121,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
41214121
<returnValue type="void *"/>
41224122
<noreturn>false</noreturn>
41234123
<leak-ignore/>
4124-
<arg nr="1" direction="out">
4124+
<arg nr="1" direction="out" indirect="1">
41254125
<not-null/>
41264126
<minsize type="argvalue" arg="3"/>
41274127
</arg>
@@ -4911,7 +4911,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
49114911
<noreturn>false</noreturn>
49124912
<not-overlapping-data ptr1-arg="1" ptr2-arg="2" strlen-arg="2"/>
49134913
<leak-ignore/>
4914-
<arg nr="1" direction="out">
4914+
<arg nr="1" direction="out" indirect="1">
49154915
<not-null/>
49164916
<minsize type="strlen" arg="2"/>
49174917
</arg>

cli/cmdlineparser.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ static bool addFilesToList(const std::string& fileList, std::vector<std::string>
7676
files = &infile;
7777
}
7878
std::string fileName;
79-
// cppcheck-suppress accessMoved - FP
8079
while (std::getline(*files, fileName)) { // next line
81-
// cppcheck-suppress accessMoved - FP
8280
if (!fileName.empty()) {
8381
pathNames.emplace_back(std::move(fileName));
8482
}
@@ -92,7 +90,6 @@ static bool addIncludePathsToList(const std::string& fileList, std::list<std::st
9290
std::ifstream files(fileList);
9391
if (files) {
9492
std::string pathName;
95-
// cppcheck-suppress accessMoved - FP
9693
while (std::getline(files, pathName)) { // next line
9794
if (!pathName.empty()) {
9895
pathName = Path::removeQuotationMarks(std::move(pathName));

cli/cppcheckexecutor.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,8 @@ namespace {
174174
{
175175
std::set<std::string> activeCheckers;
176176
std::string line;
177-
// cppcheck-suppress accessMoved - FP
178177
while (std::getline(fin, line))
179178
{
180-
// cppcheck-suppress accessMoved - FP
181179
activeCheckers.emplace(std::move(line));
182180
}
183181
mActiveCheckers = std::move(activeCheckers);

lib/astutils.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,10 +2548,11 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
25482548
const Library::ArgumentChecks::Direction argDirection = settings.library.getArgDirection(tok, 1 + argnr, indirect);
25492549
if (argDirection == Library::ArgumentChecks::Direction::DIR_IN)
25502550
return false;
2551+
if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT)
2552+
return true;
25512553

25522554
const bool requireNonNull = settings.library.isnullargbad(tok, 1 + argnr);
2553-
if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT ||
2554-
argDirection == Library::ArgumentChecks::Direction::DIR_INOUT) {
2555+
if (argDirection == Library::ArgumentChecks::Direction::DIR_INOUT) {
25552556
if (indirect == 0 && isArray(tok1))
25562557
return true;
25572558
const bool requireInit = settings.library.isuninitargbad(tok, 1 + argnr);
@@ -3471,6 +3472,9 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
34713472
const bool isuninitbad = settings.library.isuninitargbad(ftok, argnr + 1, indirect, &hasIndirect);
34723473
if (isuninitbad && (!addressOf || isnullbad))
34733474
return ExprUsage::Used;
3475+
const Library::ArgumentChecks::Direction dir = settings.library.getArgDirection(ftok, argnr + 1, indirect);
3476+
if (dir == Library::ArgumentChecks::Direction::DIR_OUT)
3477+
return ExprUsage::NotUsed;
34743478
}
34753479
return ExprUsage::Inconclusive;
34763480
}

lib/fwdanalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *
362362
while (argnr < args.size() && args[argnr] != parent)
363363
argnr++;
364364
if (argnr < args.size()) {
365-
if (mSettings.library.getArgDirection(ftok->astOperand1(), argnr + 1) == Library::ArgumentChecks::Direction::DIR_OUT)
365+
if (mSettings.library.getArgDirection(ftok->astOperand1(), argnr + 1, /*indirect*/ 1) == Library::ArgumentChecks::Direction::DIR_OUT)
366366
continue;
367367
}
368368
}

test/cfg/std.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,6 @@ void bufferAccessOutOfBounds_std_ofstream_write(std::ofstream &os, const char* s
586586
(void)os.write(s,n);
587587
}
588588

589-
// cppcheck-suppress constParameterReference // TODO: FP
590589
void bufferAccessOutOfBounds_std_ifstream_get(std::ifstream& in, std::streambuf& sb)
591590
{
592591
char cBuf[10];

test/testother.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ class TestOther : public TestFixture {
304304
TEST_CASE(moveForRange);
305305
TEST_CASE(moveTernary);
306306
TEST_CASE(movePointerAlias);
307+
TEST_CASE(moveOutparam);
307308

308309
TEST_CASE(funcArgNamesDifferent);
309310
TEST_CASE(funcArgOrderDifferent);
@@ -12550,7 +12551,8 @@ class TestOther : public TestFixture {
1255012551
" A c = a;\n"
1255112552
"}");
1255212553
ASSERT_EQUALS("[test.cpp:4:7]: (warning, inconclusive) Access of moved variable 'a'. [accessMoved]\n"
12553-
"[test.cpp:5:11]: (warning, inconclusive) Access of moved variable 'a'. [accessMoved]\n", errout_str());
12554+
"[test.cpp:5:11]: (warning, inconclusive) Access of moved variable 'a'. [accessMoved]\n",
12555+
errout_str());
1255412556
}
1255512557

1255612558
void moveAndReturn() {
@@ -12730,6 +12732,27 @@ class TestOther : public TestFixture {
1273012732
ASSERT_EQUALS("[test.cpp:5:8]: (warning) Access of moved variable '.'. [accessMoved]\n", errout_str());
1273112733
}
1273212734

12735+
void moveOutparam()
12736+
{
12737+
check("void f(std::vector<std::string>& v) {\n" // #11300
12738+
" std::string l;\n"
12739+
" while (std::getline(std::cin, l)) {\n"
12740+
" if (!l.empty()) {\n"
12741+
" v.emplace_back(std::move(l));\n"
12742+
" }\n"
12743+
" }\n"
12744+
"}\n");
12745+
ASSERT_EQUALS("", errout_str());
12746+
12747+
check("void f(std::ifstream& fin, std::set<std::string>& s) {\n"
12748+
" std::string line;\n"
12749+
" while (std::getline(fin, line)) {\n"
12750+
" s.emplace(std::move(line));\n"
12751+
" }\n"
12752+
"}\n");
12753+
ASSERT_EQUALS("", errout_str());
12754+
}
12755+
1273312756
void funcArgNamesDifferent() {
1273412757
check("void func1(int a, int b, int c);\n"
1273512758
"void func1(int a, int b, int c) { }\n"

0 commit comments

Comments
 (0)