Library configuration: function argument direction fixes and enhancements (#1722)

* std.cfg: Add further argument directions (in, out, inout).

* testlibrary.cpp: Add test for function argument direction configuration.

* std.cfg: runastyle and add some more direction configurations.

* library.h: Add documentation for function argument direction enum.

* Do not use "direction" library information for pointer arguments.

Also fix further unmatched uninitvar messages in std configuration
tests.

* std.cfg: Add more argument direction configurations.

* test/cfg/std.c: Add test for argument direction configuration.

* astutils.cpp: Only ignore pointer arguments for out/inout arguments.

* library.h: Use suggested documentation for argument direction enum.
This commit is contained in:
Sebastian 2019-03-04 22:57:40 +01:00 committed by GitHub
parent 996916358a
commit 0934577dda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 286 additions and 231 deletions

File diff suppressed because it is too large Load Diff

View File

@ -886,8 +886,13 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
if (argDirection == Library::ArgumentChecks::Direction::DIR_IN)
return false;
else if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT ||
argDirection == Library::ArgumentChecks::Direction::DIR_INOUT)
return true;
argDirection == Library::ArgumentChecks::Direction::DIR_INOUT) {
// With out or inout the direction of the content is specified, not a pointer itself, so ignore pointers for now
const ValueType * const valueType = tok1->valueType();
if (valueType && !valueType->pointer) {
return true;
}
}
}
// if the library says 0 is invalid

View File

@ -261,7 +261,12 @@ public:
};
std::vector<MinSize> minsizes;
enum Direction { DIR_IN, DIR_OUT, DIR_INOUT, DIR_UNKNOWN };
enum Direction {
DIR_IN, ///< Input to called function. Data is treated as read-only.
DIR_OUT, ///< Output to caller. Data is passed by reference or address and is potentially written.
DIR_INOUT, ///< Input to called function, and output to caller. Data is passed by reference or address and is potentially modified.
DIR_UNKNOWN ///< direction not known / specified
};
Direction direction;
};

View File

@ -75,6 +75,18 @@ void bufferAccessOutOfBounds(void)
fread(a,1,6,stdout);
}
void bufferAccessOutOfBounds_libraryDirectionConfiguration(void)
{
// This tests whether the argument to isdigit() is configured with direction "in". This allows
// Cppcheck to report the error without marking it as inconclusive.
char arr[10];
char c = 'A';
(void)isdigit(c);
// cppcheck-suppress arrayIndexOutOfBounds
// cppcheck-suppress unreadVariable
arr[c] = 'x';
}
// memory leak
void ignoreleak(void)
@ -2580,18 +2592,18 @@ void uninitvar_remquo(void)
void uninitvar_printf(char *Format, int Argument)
{
char * format;
char * format_1, * format_2, * format_3;
int argument1, argument2;
// no warning is expected
(void)printf("x");
// cppcheck-suppress uninitvar
(void)printf(format,argument1);
(void)printf(format_1,argument1);
// cppcheck-suppress uninitvar
(void)printf(Format,argument2);
// cppcheck-suppress uninitvar
(void)printf(format,Argument);
(void)printf(format_2,Argument);
// cppcheck-suppress uninitvar
(void)printf(format,1);
(void)printf(format_3,1);
// no warning is expected
(void)printf(Format,Argument);
@ -2869,14 +2881,14 @@ void bufferAccessOutOfBounds_strcat(char *dest, const char * const source)
void uninitvar_wcscat(wchar_t *dest, const wchar_t * const source)
{
wchar_t *deststr;
wchar_t *srcstr;
wchar_t *deststr_1, *deststr_2;
wchar_t *srcstr_1, *srcstr_2;
// cppcheck-suppress uninitvar
(void)wcscat(deststr,srcstr);
(void)wcscat(deststr_1,srcstr_1);
// cppcheck-suppress uninitvar
(void)wcscat(dest,srcstr);
(void)wcscat(dest,srcstr_2);
// cppcheck-suppress uninitvar
(void)wcscat(deststr,source);
(void)wcscat(deststr_2,source);
// no warning shall be shown for
(void)wcscat(dest,source);
@ -3022,13 +3034,13 @@ void uninitvar_strpbrk(void)
void uninitvar_strncat(char *Ct, char *S, size_t N)
{
char *ct;
char *ct_1, *ct_2;
char *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)strncat(ct,s,n1);
(void)strncat(ct_1,s,n1);
// cppcheck-suppress uninitvar
(void)strncat(ct,S,N);
(void)strncat(ct_2,S,N);
// cppcheck-suppress uninitvar
(void)strncat(Ct,s,N);
// cppcheck-suppress uninitvar
@ -3041,13 +3053,13 @@ void uninitvar_strncat(char *Ct, char *S, size_t N)
// errno_t strcat_s(char *restrict dest, rsize_t destsz, const char *restrict src); // since C11
void uninitvar_strcat_s(char *Ct, size_t N, char *S)
{
char *ct;
char *ct_1, *ct_2;
char *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)strcat_s(ct,n1,s);
(void)strcat_s(ct_1,n1,s);
// cppcheck-suppress uninitvar
(void)strcat_s(ct,N,S);
(void)strcat_s(ct_2,N,S);
// cppcheck-suppress uninitvar
(void)strcat_s(Ct,N,s);
// cppcheck-suppress uninitvar
@ -3060,13 +3072,13 @@ void uninitvar_strcat_s(char *Ct, size_t N, char *S)
// errno_t wcscat_s(wchar_t *restrict dest, rsize_t destsz, const wchar_t *restrict src); // since C11
void uninitvar_wcscat_s(wchar_t *Ct, size_t N, wchar_t *S)
{
wchar_t *ct;
wchar_t *ct_1, *ct_2;
wchar_t *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)wcscat_s(ct,n1,s);
(void)wcscat_s(ct_1,n1,s);
// cppcheck-suppress uninitvar
(void)wcscat_s(ct,N,S);
(void)wcscat_s(ct_2,N,S);
// cppcheck-suppress uninitvar
(void)wcscat_s(Ct,N,s);
// cppcheck-suppress uninitvar
@ -3078,7 +3090,7 @@ void uninitvar_wcscat_s(wchar_t *Ct, size_t N, wchar_t *S)
void uninitvar_strncat_s(char *Ct, size_t N1, char *S, size_t N2)
{
char *ct;
char *ct_1, *ct_2;
char *s;
size_t n1;
size_t n2;
@ -3086,9 +3098,9 @@ void uninitvar_strncat_s(char *Ct, size_t N1, char *S, size_t N2)
size_t n4;
// cppcheck-suppress uninitvar
(void)strncat_s(ct,n1,s,n2);
(void)strncat_s(ct_1,n1,s,n2);
// cppcheck-suppress uninitvar
(void)strncat_s(ct,N1,S,N2);
(void)strncat_s(ct_2,N1,S,N2);
// cppcheck-suppress uninitvar
(void)strncat_s(Ct,n3,S,N2);
// cppcheck-suppress uninitvar
@ -3102,13 +3114,13 @@ void uninitvar_strncat_s(char *Ct, size_t N1, char *S, size_t N2)
void uninitvar_wcsncat(wchar_t *Ct, wchar_t *S, size_t N)
{
wchar_t *ct;
wchar_t *ct_1, *ct_2;
wchar_t *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)wcsncat(ct,s,n1);
(void)wcsncat(ct_1,s,n1);
// cppcheck-suppress uninitvar
(void)wcsncat(ct,S,N);
(void)wcsncat(ct_2,S,N);
// cppcheck-suppress uninitvar
(void)wcsncat(Ct,s,N);
// cppcheck-suppress uninitvar

View File

@ -1962,18 +1962,18 @@ void uninitvar_remquo(void)
void uninivar_printf(char *Format, int Argument)
{
char * format;
char * format_1, * format_2, * format_3;
int argument1, argument2;
// no warning is expected
(void)std::printf("x");
// cppcheck-suppress uninitvar
(void)std::printf(format,argument1);
(void)std::printf(format_1,argument1);
// cppcheck-suppress uninitvar
(void)std::printf(Format,argument2);
// cppcheck-suppress uninitvar
(void)std::printf(format,Argument);
(void)std::printf(format_2,Argument);
// cppcheck-suppress uninitvar
(void)std::printf(format,1);
(void)std::printf(format_3,1);
// no warning is expected
(void)std::printf(Format,Argument);
@ -2251,14 +2251,14 @@ void uninitvar_strcat(char *dest, const char * const source)
void uninitvar_wcscat(wchar_t *dest, const wchar_t * const source)
{
wchar_t *deststr;
wchar_t *deststr_1, *deststr_2;
wchar_t *srcstr;
// cppcheck-suppress uninitvar
(void)std::wcscat(deststr,srcstr);
(void)std::wcscat(deststr_1,srcstr);
// cppcheck-suppress uninitvar
(void)std::wcscat(dest,srcstr);
// cppcheck-suppress uninitvar
(void)std::wcscat(deststr,source);
(void)std::wcscat(deststr_2,source);
// no warning shall be shown for
(void)std::wcscat(dest,source);
@ -2364,13 +2364,13 @@ void uninivar_strpbrk(void)
void uninivar_strncat(char *Ct, char *S, size_t N)
{
char *ct;
char *ct_1, *ct_2;
char *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)std::strncat(ct,s,n1);
(void)std::strncat(ct_1,s,n1);
// cppcheck-suppress uninitvar
(void)std::strncat(ct,S,N);
(void)std::strncat(ct_2,S,N);
// cppcheck-suppress uninitvar
(void)std::strncat(Ct,s,N);
// cppcheck-suppress uninitvar
@ -2382,13 +2382,13 @@ void uninivar_strncat(char *Ct, char *S, size_t N)
void uninivar_wcsncat(wchar_t *Ct, wchar_t *S, size_t N)
{
wchar_t *ct;
wchar_t *ct_1, *ct_2;
wchar_t *s;
size_t n1, n2;
// cppcheck-suppress uninitvar
(void)std::wcsncat(ct,s,n1);
(void)std::wcsncat(ct_1,s,n1);
// cppcheck-suppress uninitvar
(void)std::wcsncat(ct,S,N);
(void)std::wcsncat(ct_2,S,N);
// cppcheck-suppress uninitvar
(void)std::wcsncat(Ct,s,N);
// cppcheck-suppress uninitvar

View File

@ -49,6 +49,7 @@ private:
TEST_CASE(function_arg);
TEST_CASE(function_arg_any);
TEST_CASE(function_arg_variadic);
TEST_CASE(function_arg_direction);
TEST_CASE(function_arg_valid);
TEST_CASE(function_arg_minsize);
TEST_CASE(function_namespace);
@ -273,6 +274,31 @@ private:
ASSERT_EQUALS(true, library.isuninitargbad(tokenList.front(), 4));
}
void function_arg_direction() const {
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n"
"<function name=\"foo\">\n"
" <arg nr=\"1\" direction=\"in\"></arg>\n"
" <arg nr=\"2\" direction=\"out\"></arg>\n"
" <arg nr=\"3\" direction=\"inout\"></arg>\n"
" <arg nr=\"4\"></arg>\n"
"</function>\n"
"</def>";
Library library;
ASSERT_EQUALS(true, Library::OK == (readLibrary(library, xmldata)).errorcode);
TokenList tokenList(nullptr);
std::istringstream istr("foo(a,b,c,d);");
tokenList.createTokens(istr);
tokenList.front()->next()->astOperand1(tokenList.front());
ASSERT_EQUALS(Library::ArgumentChecks::Direction::DIR_IN, library.getArgDirection(tokenList.front(), 1));
ASSERT_EQUALS(Library::ArgumentChecks::Direction::DIR_OUT, library.getArgDirection(tokenList.front(), 2));
ASSERT_EQUALS(Library::ArgumentChecks::Direction::DIR_INOUT, library.getArgDirection(tokenList.front(), 3));
ASSERT_EQUALS(Library::ArgumentChecks::Direction::DIR_UNKNOWN, library.getArgDirection(tokenList.front(), 4));
}
void function_arg_valid() const {
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n"