diff --git a/CheckOther.cpp b/CheckOther.cpp index fd9533c7f..03e5b3503 100644 --- a/CheckOther.cpp +++ b/CheckOther.cpp @@ -2,6 +2,7 @@ #include "CheckOther.h" #include "Tokenize.h" #include "CommonCheck.h" +#include #include #include // <- atoi //--------------------------------------------------------------------------- @@ -288,3 +289,115 @@ void InvalidFunctionUsage() } } } +//--------------------------------------------------------------------------- + + + + +//--------------------------------------------------------------------------- +// Dangerous usage of 'strtok' +//--------------------------------------------------------------------------- + +static TOKEN *GetFunction( TOKEN *content ) +{ + TOKEN *func = NULL; + + int indentlevel = 0; + for (TOKEN *tok = tokens; tok; tok = tok->next) + { + if ( tok->str[0] == '{' ) + indentlevel++; + + else if ( tok->str[0] == '}' ) + { + indentlevel--; + if (indentlevel == 0) + func = NULL; + } + + else if (indentlevel == 0) + { + if (tok->str[0] == ';') + func = NULL; + + else if ( match(tok, "var :: var (") ) + func = tok->next->next; + + else if ( match(tok, "type var (") ) + func = tok->next; + } + + else if (indentlevel>0 && func) + { + if ( tok == content ) + return func; + } + } + return NULL; +} + +void WarningStrTok() +{ + std::list funclist; + + // Which functions contain the 'strtok'? + for (TOKEN *tok = tokens; tok; tok = tok->next) + { + if (strcmp(tok->str,"strtok")!=0) + continue; + + TOKEN *func = GetFunction(tok); + if (!func) + continue; + + funclist.push_back( func ); + } + + // No functions in list => No errors + if ( funclist.empty() ) + return; + + // Take closer look at the strtok usage. + std::list::const_iterator it1; + for (it1 = funclist.begin(); it1 != funclist.end(); it1++) + { + // Search this function to check that it doesn't call any other of + // the functions in the funclist. + int indentlevel = 0; + for ( TOKEN *tok = *it1; tok; tok = tok->next ) + { + if ( tok->str[0] == '{' ) + indentlevel++; + + else if ( tok->str[0] == '}' ) + { + if ( indentlevel <= 1 ) + break; + indentlevel--; + } + + else if ( indentlevel >= 1 ) + { + // Only interested in function calls.. + if (!(IsName(tok->str) && strcmp(getstr(tok,1), "(") == 0)) + continue; + + // Check if function name is in funclist.. + std::list::const_iterator it2; + for (it2 = funclist.begin(); it2 != funclist.end(); it2++) + { + if ( strcmp( tok->str, (*it2)->str ) ) + continue; + + std::ostringstream ostr; + ostr << FileLine(tok) << ": Possible bug. Both '" << (*it1)->str << "' and '" << (*it2)->str << "' uses strtok."; + ReportErr(ostr.str()); + } + } + } + } +} +//--------------------------------------------------------------------------- + + + diff --git a/CheckOther.h b/CheckOther.h index c2d068800..0426202df 100644 --- a/CheckOther.h +++ b/CheckOther.h @@ -25,6 +25,9 @@ void WarningDangerousFunctions(); // Invalid function usage.. void InvalidFunctionUsage(); +// Dangerous usage of 'strtok' +void WarningStrTok(); + //--------------------------------------------------------------------------- #endif diff --git a/main.cpp b/main.cpp index 4375f8e18..b33f43b5a 100644 --- a/main.cpp +++ b/main.cpp @@ -135,6 +135,9 @@ static void CppCheck(const char FileName[]) // Invalid function usage.. InvalidFunctionUsage(); + // Dangerous usage of strtok + WarningStrTok(); + // Clean up tokens.. DeallocateTokens(); } diff --git a/testfunc5/err.msg b/testfunc5/err.msg new file mode 100644 index 000000000..ca8eb5ddd --- /dev/null +++ b/testfunc5/err.msg @@ -0,0 +1 @@ +[testfunc5\testfunc5.cpp:12]: Possible bug. Both 'f2' and 'f1' uses strtok. diff --git a/testfunc5/testfunc5.cpp b/testfunc5/testfunc5.cpp new file mode 100644 index 000000000..c566a7900 --- /dev/null +++ b/testfunc5/testfunc5.cpp @@ -0,0 +1,13 @@ + + + +void f1() +{ + strtok(str,"abc"); +} + +void f2() +{ + strtok(str,"abc"); + f1(); +} \ No newline at end of file