library: add attribute strlen-arg for <not-overlapping-data>
This commit is contained in:
parent
17d5dc4d8a
commit
ce58748690
|
@ -176,6 +176,9 @@
|
|||
<optional>
|
||||
<attribute name="size-arg"><data type="positiveInteger"/></attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="strlen-arg"><data type="positiveInteger"/></attribute>
|
||||
</optional>
|
||||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
|
|
|
@ -4769,6 +4769,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
|||
<function name="strcpy,std::strcpy">
|
||||
<returnValue type="char *">arg1</returnValue>
|
||||
<noreturn>false</noreturn>
|
||||
<not-overlapping-data ptr1-arg="1" ptr2-arg="2" strlen-arg="2"/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1" direction="out">
|
||||
<not-null/>
|
||||
|
|
|
@ -3438,15 +3438,35 @@ void CheckOther::checkOverlappingWrite()
|
|||
continue;
|
||||
if (nonOverlappingData->ptr2Arg <= 0 || nonOverlappingData->ptr2Arg > args.size())
|
||||
continue;
|
||||
if (nonOverlappingData->sizeArg <= 0 || nonOverlappingData->sizeArg > args.size())
|
||||
|
||||
const Token *ptr1 = args[nonOverlappingData->ptr1Arg - 1];
|
||||
if (ptr1->hasKnownIntValue() && ptr1->getKnownIntValue() == 0)
|
||||
continue;
|
||||
|
||||
const Token *ptr2 = args[nonOverlappingData->ptr2Arg - 1];
|
||||
if (ptr2->hasKnownIntValue() && ptr2->getKnownIntValue() == 0)
|
||||
continue;
|
||||
|
||||
// TODO: nonOverlappingData->strlenArg
|
||||
if (nonOverlappingData->sizeArg <= 0 || nonOverlappingData->sizeArg > args.size()) {
|
||||
if (nonOverlappingData->sizeArg == -1) {
|
||||
ErrorPath errorPath;
|
||||
const bool macro = true;
|
||||
const bool pure = true;
|
||||
const bool follow = true;
|
||||
if (!isSameExpression(mTokenizer->isCPP(), macro, ptr1, ptr2, mSettings->library, pure, follow, &errorPath))
|
||||
continue;
|
||||
overlappingWriteFunction(tok);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!args[nonOverlappingData->sizeArg-1]->hasKnownIntValue())
|
||||
continue;
|
||||
const Token *buf1, *buf2;
|
||||
MathLib::bigint offset1, offset2;
|
||||
if (!getBufAndOffset(args[nonOverlappingData->ptr1Arg-1], &buf1, &offset1))
|
||||
if (!getBufAndOffset(ptr1, &buf1, &offset1))
|
||||
continue;
|
||||
if (!getBufAndOffset(args[nonOverlappingData->ptr2Arg-1], &buf2, &offset2))
|
||||
if (!getBufAndOffset(ptr2, &buf2, &offset2))
|
||||
continue;
|
||||
|
||||
ErrorPath errorPath;
|
||||
|
|
|
@ -645,6 +645,7 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
nonOverlappingData.ptr1Arg = functionnode->IntAttribute("ptr1-arg", -1);
|
||||
nonOverlappingData.ptr2Arg = functionnode->IntAttribute("ptr2-arg", -1);
|
||||
nonOverlappingData.sizeArg = functionnode->IntAttribute("size-arg", -1);
|
||||
nonOverlappingData.strlenArg = functionnode->IntAttribute("strlen-arg", -1);
|
||||
mNonOverlappingData[name] = nonOverlappingData;
|
||||
} else if (functionnodename == "use-retval") {
|
||||
func.useretval = Library::UseRetValType::DEFAULT;
|
||||
|
|
|
@ -172,6 +172,7 @@ public:
|
|||
int ptr1Arg;
|
||||
int ptr2Arg;
|
||||
int sizeArg;
|
||||
int strlenArg;
|
||||
};
|
||||
const NonOverlappingData* getNonOverlappingData(const Token *ftok) const;
|
||||
|
||||
|
|
|
@ -9361,6 +9361,12 @@ private:
|
|||
" wmemcpy(a, a+1, 2u);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Overlapping read/write in wmemcpy() is undefined behavior\n", errout.str());
|
||||
|
||||
// strcpy
|
||||
check("void foo(char *ptr) {\n"
|
||||
" strcpy(ptr, ptr);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (error) Overlapping read/write in strcpy() is undefined behavior\n", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue