Fixed FPs from Ticket 11119 - invalidFunctionArgStr with null-terminated strings (#4164)

* Fixed first FP from #11119 - invalidFunctionArgStr with null-terminated strings

* Fixed second test case from #11119.

* Fixed another FP, found on daca@home ftp://ftp.de.debian.org/debian/pool/main/g/glhack/glhack_1.2.orig.tar.gz.

* Format
This commit is contained in:
orbitcowboy 2022-06-02 19:30:29 +02:00 committed by GitHub
parent 58460edaf8
commit 67795cdfcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 6 deletions

View File

@ -3630,7 +3630,6 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
<not-uninit/> <not-uninit/>
<not-null/> <not-null/>
<minsize type="argvalue" arg="3"/> <minsize type="argvalue" arg="3"/>
<strz/>
</arg> </arg>
<arg nr="3" direction="in"> <arg nr="3" direction="in">
<not-uninit/> <not-uninit/>

View File

@ -4979,7 +4979,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<arg nr="2" direction="in"> <arg nr="2" direction="in">
<not-null/> <not-null/>
<not-uninit/> <not-uninit/>
<strz/>
</arg> </arg>
<arg nr="3" direction="in"> <arg nr="3" direction="in">
<not-uninit/> <not-uninit/>

View File

@ -150,14 +150,18 @@ void CheckFunctions::invalidFunctionUsage()
} }
if (Token::simpleMatch(varTok, "= {")) { if (Token::simpleMatch(varTok, "= {")) {
varTok = varTok->tokAt(1); varTok = varTok->tokAt(1);
auto actualCharCount = 0; auto charsUntilFirstZero = 0;
while (varTok && !Token::simpleMatch(varTok->next(), "}")) { while (varTok && !Token::simpleMatch(varTok->next(), "}")) {
if (!Token::simpleMatch(varTok->next(), ",")) if (!Token::simpleMatch(varTok->next(), ",")) {
++actualCharCount; ++charsUntilFirstZero;
}
varTok = varTok->next(); varTok = varTok->next();
if (varTok && varTok->hasKnownIntValue() && varTok->getKnownIntValue() == 0) {
break; // stop counting for cases like char buf[3] = {'x', '\0', 'y'};
}
} }
if (varTok && varTok->hasKnownIntValue() && varTok->getKnownIntValue() != 0 if (varTok && varTok->hasKnownIntValue() && varTok->getKnownIntValue() != 0
&& (count == -1 || (count > 0 && count <= actualCharCount))) { && (count == -1 || (count > 0 && count <= charsUntilFirstZero))) {
invalidFunctionArgStrError(argtok, functionToken->str(), argnr); invalidFunctionArgStrError(argtok, functionToken->str(), argnr);
} }
} }

View File

@ -35,6 +35,17 @@
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
void invalidFunctionArgStr_mbsnrtowcs(void)
{
wchar_t wenough[10];
mbstate_t s;
memset (&s, '\0', sizeof (s));
const char* cp = "ABC";
wcscpy (wenough, L"DEF");
// No warning is expected for - #11119
if (mbsnrtowcs (wenough, &cp, 1, 10, &s) != 1 || wcscmp (wenough, L"AEF") != 0) {}
}
int nullPointer_getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) int nullPointer_getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
{ {
// cppcheck-suppress nullPointer // cppcheck-suppress nullPointer

View File

@ -36,6 +36,17 @@
#include <iterator> #include <iterator>
#include <vector> #include <vector>
char* invalidFunctionArgStr_strncpy(char * destination)
{
// Copies the first num characters of source to destination.
// If the end of the source C string (which is signaled by a null-character)
// is found before num characters have been copied, destination
// is padded with zeros until a total of num characters have been written to it.
const char source = 'x';
const std::size_t num = 1U;
return strncpy(destination, &source, num);
}
void invalidFunctionArgStr_fprintf(FILE *stream, const char *format) void invalidFunctionArgStr_fprintf(FILE *stream, const char *format)
{ {
const char formatBuf[] = {'%','d'}; const char formatBuf[] = {'%','d'};

View File

@ -632,6 +632,12 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("FILE* f(void) {\n"
" const char fileName[3] = { \'x\', \'\\0\' ,\'y\' };\n"
" return fopen(fileName, \"r\"); \n"
"}");
ASSERT_EQUALS("", errout.str());
check("FILE* f(void) {\n" check("FILE* f(void) {\n"
" const char fileName[3] = { \'x\', \'y\' };\n" // implicit '\0' added at the end " const char fileName[3] = { \'x\', \'y\' };\n" // implicit '\0' added at the end
" return fopen(fileName, \"r\"); \n" " return fopen(fileName, \"r\"); \n"