Skip to content

Commit ce58748

Browse files
committed
library: add attribute strlen-arg for <not-overlapping-data>
1 parent 17d5dc4 commit ce58748

File tree

6 files changed

+35
-3
lines changed

6 files changed

+35
-3
lines changed

cfg/cppcheck-cfg.rng

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
<optional>
177177
<attribute name="size-arg"><data type="positiveInteger"/></attribute>
178178
</optional>
179+
<optional>
180+
<attribute name="strlen-arg"><data type="positiveInteger"/></attribute>
181+
</optional>
179182
<empty/>
180183
</element>
181184
</optional>

cfg/std.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4769,6 +4769,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
47694769
<function name="strcpy,std::strcpy">
47704770
<returnValue type="char *">arg1</returnValue>
47714771
<noreturn>false</noreturn>
4772+
<not-overlapping-data ptr1-arg="1" ptr2-arg="2" strlen-arg="2"/>
47724773
<leak-ignore/>
47734774
<arg nr="1" direction="out">
47744775
<not-null/>

lib/checkother.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3438,15 +3438,35 @@ void CheckOther::checkOverlappingWrite()
34383438
continue;
34393439
if (nonOverlappingData->ptr2Arg <= 0 || nonOverlappingData->ptr2Arg > args.size())
34403440
continue;
3441-
if (nonOverlappingData->sizeArg <= 0 || nonOverlappingData->sizeArg > args.size())
3441+
3442+
const Token *ptr1 = args[nonOverlappingData->ptr1Arg - 1];
3443+
if (ptr1->hasKnownIntValue() && ptr1->getKnownIntValue() == 0)
3444+
continue;
3445+
3446+
const Token *ptr2 = args[nonOverlappingData->ptr2Arg - 1];
3447+
if (ptr2->hasKnownIntValue() && ptr2->getKnownIntValue() == 0)
3448+
continue;
3449+
3450+
// TODO: nonOverlappingData->strlenArg
3451+
if (nonOverlappingData->sizeArg <= 0 || nonOverlappingData->sizeArg > args.size()) {
3452+
if (nonOverlappingData->sizeArg == -1) {
3453+
ErrorPath errorPath;
3454+
const bool macro = true;
3455+
const bool pure = true;
3456+
const bool follow = true;
3457+
if (!isSameExpression(mTokenizer->isCPP(), macro, ptr1, ptr2, mSettings->library, pure, follow, &errorPath))
3458+
continue;
3459+
overlappingWriteFunction(tok);
3460+
}
34423461
continue;
3462+
}
34433463
if (!args[nonOverlappingData->sizeArg-1]->hasKnownIntValue())
34443464
continue;
34453465
const Token *buf1, *buf2;
34463466
MathLib::bigint offset1, offset2;
3447-
if (!getBufAndOffset(args[nonOverlappingData->ptr1Arg-1], &buf1, &offset1))
3467+
if (!getBufAndOffset(ptr1, &buf1, &offset1))
34483468
continue;
3449-
if (!getBufAndOffset(args[nonOverlappingData->ptr2Arg-1], &buf2, &offset2))
3469+
if (!getBufAndOffset(ptr2, &buf2, &offset2))
34503470
continue;
34513471

34523472
ErrorPath errorPath;

lib/library.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
645645
nonOverlappingData.ptr1Arg = functionnode->IntAttribute("ptr1-arg", -1);
646646
nonOverlappingData.ptr2Arg = functionnode->IntAttribute("ptr2-arg", -1);
647647
nonOverlappingData.sizeArg = functionnode->IntAttribute("size-arg", -1);
648+
nonOverlappingData.strlenArg = functionnode->IntAttribute("strlen-arg", -1);
648649
mNonOverlappingData[name] = nonOverlappingData;
649650
} else if (functionnodename == "use-retval") {
650651
func.useretval = Library::UseRetValType::DEFAULT;

lib/library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class CPPCHECKLIB Library {
172172
int ptr1Arg;
173173
int ptr2Arg;
174174
int sizeArg;
175+
int strlenArg;
175176
};
176177
const NonOverlappingData* getNonOverlappingData(const Token *ftok) const;
177178

test/testother.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9361,6 +9361,12 @@ class TestOther : public TestFixture {
93619361
" wmemcpy(a, a+1, 2u);\n"
93629362
"}");
93639363
ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in wmemcpy() is undefined behavior\n", errout.str());
9364+
9365+
// strcpy
9366+
check("void foo(char *ptr) {\n"
9367+
" strcpy(ptr, ptr);\n"
9368+
"}");
9369+
ASSERT_EQUALS("[test.cpp:2]: (error) Overlapping read/write in strcpy() is undefined behavior\n", errout.str());
93649370
}
93659371
};
93669372

0 commit comments

Comments
 (0)