From bbe06c65c0e6f282c5063985c9160b8abc440e22 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Tue, 6 Nov 2012 10:54:52 -0800 Subject: [PATCH] Added support for wide-strings (wcs* functions, std::wstring, std::*wstringstream) at many places. --- lib/checkio.cpp | 8 ++-- lib/checknullpointer.cpp | 81 ++++++++++++++++++++++++++++++++++------ lib/checkother.cpp | 20 +++++----- lib/checkstl.cpp | 18 ++++----- 4 files changed, 93 insertions(+), 34 deletions(-) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index cf6f711a2..00d593018 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -424,7 +424,7 @@ void CheckIO::checkWrongPrintfScanfArguments() const Token* argListTok = 0; // Points to first va_list argument std::string formatString; - if (Token::Match(tok, "printf|scanf ( %str%")) { + if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%")) { formatString = tok->strAt(2); if (tok->strAt(3) == ",") { argListTok = tok->tokAt(4); @@ -433,7 +433,7 @@ void CheckIO::checkWrongPrintfScanfArguments() } else { continue; } - } else if (Token::Match(tok, "sprintf|fprintf|sscanf|fscanf ( %any%")) { + } else if (Token::Match(tok, "sprintf|fprintf|sscanf|fscanf|swscanf|fwprintf|fwscanf ( %any%")) { const Token* formatStringTok = tok->tokAt(2)->nextArgument(); // Find second parameter (format string) if (Token::Match(formatStringTok, "%str% ,")) { argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args) @@ -444,7 +444,7 @@ void CheckIO::checkWrongPrintfScanfArguments() } else { continue; } - } else if (Token::Match(tok, "snprintf|fnprintf (")) { + } else if (Token::Match(tok, "snprintf|fnprintf|swprintf (")) { const Token* formatStringTok = tok->tokAt(2); for (int i = 0; i < 2 && formatStringTok; i++) { formatStringTok = formatStringTok->nextArgument(); // Find third parameter (format string) @@ -463,7 +463,7 @@ void CheckIO::checkWrongPrintfScanfArguments() } // Count format string parameters.. - bool scan = Token::Match(tok, "sscanf|fscanf|scanf"); + bool scan = Token::Match(tok, "sscanf|fscanf|scanf|swscanf|fwscanf|wscanf"); unsigned int numFormat = 0; bool percent = false; const Token* argListTok2 = argListTok; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 1afc733e3..4e77e1a81 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -51,9 +51,20 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::liststrValue(); argListTok = secondParam; - } else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf")) { + } else if (Token::Match(&tok, "sprintf|fprintf|sscanf|fscanf|fwprintf|fwscanf|swscanf")) { const Token* formatStringTok = secondParam; // Find second parameter (format string) if (formatStringTok && formatStringTok->type() == Token::eString) { argListTok = formatStringTok->nextArgument(); // Find third parameter (first argument of va_args) formatString = formatStringTok->strValue(); } - } else if (Token::Match(&tok, "snprintf|fnprintf") && secondParam) { + } else if (Token::Match(&tok, "snprintf|fnprintf|swprintf") && secondParam) { const Token* formatStringTok = secondParam->nextArgument(); // Find third parameter (format string) if (formatStringTok && formatStringTok->type() == Token::eString) { argListTok = formatStringTok->nextArgument(); // Find fourth parameter (first argument of va_args) @@ -309,7 +368,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym return true; if (tok2 && tok2->varId() != 0) { const Variable* var2 = symbolDatabase->getVariableFromVarId(tok2->varId()); - if (var2 && Token::Match(var2->typeStartToken(), "std :: istream|ifstream|istringstream|ostream|ofstream|ostringstream|stringstream|fstream|iostream")) + if (var2 && Token::Match(var2->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|ostream|ofstream|ostringstream|wostringstream|stringstream|wstringstream|fstream|iostream")) return true; } } @@ -324,7 +383,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Sym ovarid = tok->tokAt(-2)->varId(); if (ovarid) { const Variable* var = symbolDatabase->getVariableFromVarId(ovarid); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) return true; } @@ -1060,7 +1119,7 @@ void CheckNullPointer::nullConstantDereference() else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) nullPointerError(tok); } else { // function call std::list var; @@ -1073,7 +1132,7 @@ void CheckNullPointer::nullConstantDereference() } } } - } else if (Token::simpleMatch(tok, "std :: string ( 0 )")) + } else if (Token::Match(tok, "std :: string|wstring ( 0 )")) nullPointerError(tok); else if (Token::simpleMatch(tok->previous(), ">> 0")) { // Only checking input stream operations is safe here, because otherwise 0 can be an integer as well @@ -1086,7 +1145,7 @@ void CheckNullPointer::nullConstantDereference() nullPointerError(tok); if (tok2 && tok2->varId() != 0) { const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId()); - if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|stringstream|fstream|iostream")) + if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|stringstream|wstringstream|fstream|iostream")) nullPointerError(tok); } } @@ -1100,7 +1159,7 @@ void CheckNullPointer::nullConstantDereference() ovarid = tok->varId(); if (ovarid) { const Variable* var = symbolDatabase->getVariableFromVarId(ovarid); - if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string !!::")) + if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) nullPointerError(tok); } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 12a29e073..a402424b1 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -692,11 +692,11 @@ void CheckOther::checkRedundantAssignment() memAssignments.erase(tok->varId()); } } else if (Token::Match(tok, "%var% (")) { // Function call. Global variables might be used. Reset their status - bool memfunc = Token::Match(tok, "memcpy|memmove|memset|strcpy|strncpy|sprintf|snprintf|strcat|strncat"); + bool memfunc = Token::Match(tok, "memcpy|memmove|memset|strcpy|strncpy|sprintf|snprintf|strcat|strncat|wcscpy|wcsncpy|swprintf|wcscat|wcsncat"); if (memfunc) { const Token* param1 = tok->tokAt(2); writtenArgumentsEnd = param1->next(); - if (param1->varId() && param1->strAt(1) == "," && tok->str() != "strcat" && tok->str() != "strncat") { + if (param1->varId() && param1->strAt(1) == "," && !Token::Match(tok, "strcat|strncat|wcscat|wcsncat")) { std::map::iterator it = memAssignments.find(param1->varId()); if (it == memAssignments.end()) memAssignments[param1->varId()] = tok; @@ -1390,7 +1390,7 @@ void CheckOther::invalidFunctionUsage() { // strtol and strtoul.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { - if (!Token::Match(tok, "strtol|strtoul (")) + if (!Token::Match(tok, "strtol|strtoul|strtoll|strtoull|wcstol|wcstoul|wcstoll|wcstoull (")) continue; const std::string& funcname = tok->str(); @@ -1413,10 +1413,10 @@ void CheckOther::invalidFunctionUsage() // Get variable id of target buffer.. unsigned int varid = 0; - if (Token::Match(tok, "sprintf|snprintf ( %var% ,")) + if (Token::Match(tok, "sprintf|snprintf|swprintf ( %var% ,")) varid = tok->tokAt(2)->varId(); - else if (Token::Match(tok, "sprintf|snprintf ( %var% . %var% ,")) + else if (Token::Match(tok, "sprintf|snprintf|swprintf ( %var% . %var% ,")) varid = tok->tokAt(4)->varId(); if (varid == 0) @@ -1429,7 +1429,7 @@ void CheckOther::invalidFunctionUsage() tok2 = tok2->next(); // Jump behind "," - if (tok->str() == "snprintf") { // Jump over second parameter for snprintf + if (tok->str() == "snprintf" || tok->str() == "swprintf") { // Jump over second parameter for snprintf and swprintf tok2 = tok2->nextArgument(); if (!tok2) continue; @@ -2653,7 +2653,7 @@ void CheckOther::checkDoubleFree() } // If a variable is passed to a function, remove it from the set of previously freed variables - else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf")) { + else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf|wprintf|swprintf|fwprintf")) { // If this is a new function definition, clear all variables if (Token::simpleMatch(tok->next()->link(), ") {")) { @@ -2749,7 +2749,7 @@ namespace { v = symbolDatabase->getVariableFromVarId(scope->varId()); } // hard coded list of safe, no-side-effect functions - if (v == 0 && Token::Match(prev, "strcmp|strncmp|strlen|memcmp|strcasecmp|strncasecmp")) + if (v == 0 && Token::Match(prev, "strcmp|strncmp|strlen|wcscmp|wcsncmp|wcslen|memcmp|strcasecmp|strncasecmp")) return false; std::list::const_iterator it = std::find_if(constFunctions.begin(), constFunctions.end(), @@ -3039,9 +3039,9 @@ void CheckOther::checkAlwaysTrueOrFalseStringCompare() if (!_settings->isEnabled("style")) return; - const char pattern1[] = "strncmp|strcmp|stricmp|strcmpi|strcasecmp|wcscmp ( %str% , %str% "; + const char pattern1[] = "strncmp|strcmp|stricmp|strcmpi|strcasecmp|wcscmp|wcsncmp ( %str% , %str% "; const char pattern2[] = "QString :: compare ( %str% , %str% )"; - const char pattern3[] = "strncmp|strcmp|stricmp|strcmpi|strcasecmp|wcscmp ( %var% , %var% "; + const char pattern3[] = "strncmp|strcmp|stricmp|strcmpi|strcasecmp|wcscmp|wcsncmp ( %var% , %var% "; const Token *tok = _tokenizer->tokens(); while (tok && (tok = Token::findmatch(tok, pattern1)) != NULL) { diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 3840812ab..b863bbd74 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -790,7 +790,7 @@ void CheckStl::if_find() // stl container if (Token::Match(decl, "std :: %var% < %type% > &| %varid%", varid)) if_findError(tok, false); - else if (Token::Match(decl, "std :: string &| %varid%", varid)) + else if (Token::Match(decl, "std :: string|wstring &| %varid%", varid)) if_findError(tok, true); } } @@ -839,7 +839,7 @@ void CheckStl::if_find() if_findError(tok, false); } - else if (Token::Match(decl, "std :: string > &| %varid%", varid)) + else if (Token::Match(decl, "std :: string|wstring > &| %varid%", varid)) if_findError(tok, true); } @@ -1133,11 +1133,11 @@ void CheckStl::string_c_str() continue; enum {charPtr, stdString, stdStringConstRef, Other} returnType = Other; - if (Token::simpleMatch(scope->function->tokenDef->tokAt(-2), "char *")) + if (Token::Match(scope->function->tokenDef->tokAt(-2), "char|wchar_t *")) returnType = charPtr; - else if (Token::simpleMatch(scope->function->tokenDef->tokAt(-5), "const std :: string &")) + else if (Token::Match(scope->function->tokenDef->tokAt(-5), "const std :: string|wstring &")) returnType = stdStringConstRef; - else if (Token::Match(scope->function->tokenDef->tokAt(-3), "std :: string !!&")) + else if (Token::Match(scope->function->tokenDef->tokAt(-3), "std :: string|wstring !!&")) returnType = stdString; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { @@ -1150,7 +1150,7 @@ void CheckStl::string_c_str() string_c_strError(tok); } else if (Token::Match(tok, "[;{}] %var% = %var% (") && Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;") && - Token::findmatch(_tokenizer->tokens(), ("std :: string " + tok->strAt(3) + " (").c_str())) { + Token::findmatch(_tokenizer->tokens(), ("std :: string|wstring " + tok->strAt(3) + " (").c_str())) { const Variable* var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); if (var && var->isPointer()) string_c_strError(tok); @@ -1184,12 +1184,12 @@ void CheckStl::string_c_str() string_c_strError(tok); } else if (Token::Match(tok, "return %var% . str ( ) . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) { string_c_strError(tok); - } else if (Token::simpleMatch(tok, "return std :: string (") && + } else if (Token::Match(tok, "return std :: string|wstring (") && Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;")) { string_c_strError(tok); } else if (Token::Match(tok, "return %var% (") && Token::simpleMatch(tok->linkAt(2), ") . c_str ( ) ;")) { const Function* func =_tokenizer->getSymbolDatabase()->findFunctionByName(tok->strAt(1), tok->scope());; - if (func && Token::simpleMatch(func->tokenDef->tokAt(-3), "std :: string")) + if (func && Token::Match(func->tokenDef->tokAt(-3), "std :: string|wstring")) string_c_strError(tok); } else if (Token::simpleMatch(tok, "return (") && Token::simpleMatch(tok->next()->link(), ") . c_str ( ) ;")) { @@ -1200,7 +1200,7 @@ void CheckStl::string_c_str() if (Token::Match(search_tok, "+ %var%") && isLocal(symbolDatabase, search_tok->next()->varId())) { is_implicit_std_string = true; break; - } else if (Token::simpleMatch(search_tok, "+ std :: string (")) { + } else if (Token::Match(search_tok, "+ std :: string|wstring (")) { is_implicit_std_string = true; break; }