diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng
index 595afb2be..45cff6c91 100644
--- a/cfg/cppcheck-cfg.rng
+++ b/cfg/cppcheck-cfg.rng
@@ -176,6 +176,9 @@
+
+
+
diff --git a/cfg/std.cfg b/cfg/std.cfg
index c7b1b788f..2b06a8ec7 100644
--- a/cfg/std.cfg
+++ b/cfg/std.cfg
@@ -4769,6 +4769,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
arg1
false
+
diff --git a/lib/checkother.cpp b/lib/checkother.cpp
index f41109da3..141665b22 100644
--- a/lib/checkother.cpp
+++ b/lib/checkother.cpp
@@ -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;
diff --git a/lib/library.cpp b/lib/library.cpp
index c7c4154c8..7d1ee95a1 100644
--- a/lib/library.cpp
+++ b/lib/library.cpp
@@ -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;
diff --git a/lib/library.h b/lib/library.h
index f452852f4..040a6c5b8 100644
--- a/lib/library.h
+++ b/lib/library.h
@@ -172,6 +172,7 @@ public:
int ptr1Arg;
int ptr2Arg;
int sizeArg;
+ int strlenArg;
};
const NonOverlappingData* getNonOverlappingData(const Token *ftok) const;
diff --git a/test/testother.cpp b/test/testother.cpp
index 594b36f43..2c914e947 100644
--- a/test/testother.cpp
+++ b/test/testother.cpp
@@ -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());
}
};