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:
parent
996916358a
commit
0934577dda
389
cfg/std.cfg
389
cfg/std.cfg
File diff suppressed because it is too large
Load Diff
|
@ -886,9 +886,14 @@ 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)
|
||||
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
|
||||
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue