Fix #8381: false positives for swprintf_ and stprintf_s (#1080)

This fixes false positives because of wrong configuration in
windows.cfg.
Add tests in testio.cpp and test/cfg/windows.cpp to avoid regression.
This commit is contained in:
Sebastian 2018-02-03 05:10:52 +01:00 committed by amai2012
parent c235930539
commit 2e5d7a8391
3 changed files with 113 additions and 14 deletions

View File

@ -1914,23 +1914,17 @@
<not-uninit/>
</arg>
</function>
<!-- int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);-->
<!-- template <size_t size> int sprintf_s(char (&buffer)[size], const char *format, ...); // C++ only -->
<!-- int swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...); -->
<function name="swprintf_s">
<!-- template <size_t size> int swprintf_s(wchar_t (&buffer)[size], const wchar_t *format, ...); // C++ only -->
<function name="sprintf_s,swprintf_s">
<noreturn>false</noreturn>
<returnValue type="int"/>
<leak-ignore/>
<arg nr="1">
<minsize type="argvalue" arg="2"/>
</arg>
<arg nr="2">
<not-uninit/>
<valid>0:</valid>
</arg>
<formatstr/>
<arg nr="3">
<formatstr/>
<not-null/>
<not-uninit/>
</arg>
<!-- These functions and the format string checking is completely
implemented in Cppcheck. It can not (yet) be configured in the configuration
file. See #8381 -->
</function>
<!-- int _sprintf_s_l(char *buffer, size_t sizeOfBuffer, const char *format, locale_t locale, ... );
int _swprintf_s_l(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, locale_t locale, ...);-->

View File

@ -94,6 +94,28 @@ void validCode()
pMem = HeapReAlloc(GetProcessHeap(), 0, pMem, 0);
HeapFree(GetProcessHeap(), 0, pMem);
char bufC[50];
sprintf_s(bufC, "Hello");
printf("%s", bufC);
sprintf_s(bufC, "%s", "test");
printf("%s", bufC);
sprintf_s(bufC, _countof(bufC), "%s", "test");
printf("%s", bufC);
wchar_t bufWC[50];
swprintf_s(bufWC, L"Hello");
wprintf(L"%s\n", bufWC);
swprintf_s(bufWC, L"%s %d", L"swprintf_s", 3);
wprintf(L"%s\n", bufWC);
swprintf_s(bufWC, _countof(bufWC), L"%s %d", L"swprintf_s", 6);
wprintf(L"%s\n", bufWC);
TCHAR bufTC[50];
_stprintf(bufTC, TEXT("Hello"));
_tprintf(TEXT("%s"), bufTC);
_stprintf(bufTC, TEXT("%d"), 1);
_tprintf(TEXT("%s"), bufTC);
_stprintf(bufTC, _countof(bufTC), TEXT("%d"), 2);
_tprintf(TEXT("%s"), bufTC);
// Valid Library usage, no leaks, valid arguments
HINSTANCE hInstLib = LoadLibrary(L"My.dll");
FreeLibrary(hInstLib);
@ -415,6 +437,69 @@ void uninitvar()
SetLastError(dwordUninit);
}
void errorPrintf()
{
char bufC[50];
// cppcheck-suppress wrongPrintfScanfArgNum
sprintf_s(bufC, _countof(bufC), "%s %d", "sprintf_s");
printf("%s\n", bufC);
// cppcheck-suppress wrongPrintfScanfArgNum
sprintf_s(bufC, "%s %d", "sprintf_s");
printf("%s\n", bufC);
// cppcheck-suppress wrongPrintfScanfArgNum
sprintf_s(bufC, _countof(bufC), "test", 0);
printf("%s\n", bufC);
// cppcheck-suppress wrongPrintfScanfArgNum
sprintf_s(bufC, "test", "sprintf_s");
printf("%s\n", bufC);
// cppcheck-suppress invalidPrintfArgType_s
sprintf_s(bufC, _countof(bufC), "%s", 1);
printf("%s\n", bufC);
// cppcheck-suppress invalidPrintfArgType_s
sprintf_s(bufC, "%s", 1);
printf("%s\n", bufC);
wchar_t bufWC[50];
// cppcheck-suppress wrongPrintfScanfArgNum
swprintf_s(bufWC, _countof(bufWC), L"%s %d", L"swprintf_s");
wprintf(L"%s\n", bufWC);
// cppcheck-suppress wrongPrintfScanfArgNum
swprintf_s(bufWC, L"%s %d", L"swprintf_s");
wprintf(L"%s\n", bufWC);
// cppcheck-suppress wrongPrintfScanfArgNum
swprintf_s(bufWC, _countof(bufWC), L"test", 0);
wprintf(L"%s\n", bufWC);
// cppcheck-suppress wrongPrintfScanfArgNum
swprintf_s(bufWC, L"test", L"swprintf_s");
wprintf(L"%s\n", bufWC);
// cppcheck-suppress invalidPrintfArgType_s
swprintf_s(bufWC, _countof(bufWC), L"%s", 1);
wprintf(L"%s\n", bufWC);
// cppcheck-suppress invalidPrintfArgType_s
swprintf_s(bufWC, L"%s", 1);
wprintf(L"%s\n", bufWC);
TCHAR bufTC[50];
// cppcheck-suppress wrongPrintfScanfArgNum
_stprintf_s(bufTC, _countof(bufTC), TEXT("%s %d"), TEXT("_stprintf_s"));
_tprintf(L"%s\n", bufTC);
// cppcheck-suppress wrongPrintfScanfArgNum
_stprintf_s(bufTC, TEXT("%s %d"), TEXT("_stprintf_s"));
_tprintf(TEXT("%s\n"), bufTC);
// cppcheck-suppress wrongPrintfScanfArgNum
_stprintf_s(bufTC, _countof(bufTC), TEXT("test"), 0);
_tprintf(TEXT("%s\n"), bufTC);
// cppcheck-suppress wrongPrintfScanfArgNum
_stprintf_s(bufTC, TEXT("test"), TEXT("_stprintf_s"));
_tprintf(TEXT("%s\n"), bufTC);
// cppcheck-suppress invalidPrintfArgType_s
_stprintf_s(bufTC, _countof(bufTC), TEXT("%s"), 1);
_tprintf(TEXT("%s\n"), bufTC);
// cppcheck-suppress invalidPrintfArgType_s
_stprintf_s(bufTC, TEXT("%s"), 1);
_tprintf(TEXT("%s\n"), bufTC);
}
void allocDealloc_GetModuleHandleEx()
{
// For GetModuleHandleEx it depends on the first argument if FreeLibrary

View File

@ -4322,6 +4322,16 @@ private:
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
"[test.cpp:5]: (warning) sprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
check("void foo() {\n"
" char str[10];\n"
" int i;\n"
" unsigned int u;\n"
" sprintf_s(str, \"%d %u\", u, i, 0);\n"
"}\n", false, false, Settings::Win32A);
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
"[test.cpp:5]: (warning) sprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
check("void foo() {\n"
" wchar_t str[10];\n"
" int i;\n"
@ -4332,6 +4342,16 @@ private:
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
"[test.cpp:5]: (warning) swprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
check("void foo() {\n"
" wchar_t str[10];\n"
" int i;\n"
" unsigned int u;\n"
" swprintf_s(str, L\"%d %u\", u, i, 0);\n"
"}\n", false, false, Settings::Win32W);
ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'.\n"
"[test.cpp:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
"[test.cpp:5]: (warning) swprintf_s format string requires 2 parameters but 3 are given.\n", errout.str());
check("void foo() {\n"
" TCHAR str[10];\n"
" int i;\n"