Added support for wide-strings (wcs* functions, std::wstring, std::*wstringstream) at many places.

This commit is contained in:
PKEuS 2012-11-06 10:54:52 -08:00
parent 51d128c918
commit bbe06c65c0
4 changed files with 93 additions and 34 deletions

View File

@ -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;

View File

@ -51,9 +51,20 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
functionNames1_all.insert("atof");
functionNames1_all.insert("atol");
functionNames1_all.insert("qsort");
functionNames1_all.insert("strtof");
functionNames1_all.insert("strtod");
functionNames1_all.insert("strtol");
functionNames1_all.insert("strtoul");
functionNames1_all.insert("strtold");
functionNames1_all.insert("strtoll");
functionNames1_all.insert("strtoull");
functionNames1_all.insert("wcstof");
functionNames1_all.insert("wcstod");
functionNames1_all.insert("wcstol");
functionNames1_all.insert("wcstoul");
functionNames1_all.insert("wcstold");
functionNames1_all.insert("wcstoll");
functionNames1_all.insert("wcstoull");
// cstring
functionNames1_all.insert("memchr");
functionNames1_all.insert("memcmp");
@ -71,6 +82,20 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
functionNames1_all.insert("strlen");
functionNames1_all.insert("strspn");
functionNames1_all.insert("strstr");
functionNames1_all.insert("wcscat");
functionNames1_all.insert("wcsncat");
functionNames1_all.insert("wcscoll");
functionNames1_all.insert("wcschr");
functionNames1_all.insert("wcsrchr");
functionNames1_all.insert("wcscmp");
functionNames1_all.insert("wcsncmp");
functionNames1_all.insert("wcscspn");
functionNames1_all.insert("wcsdup");
functionNames1_all.insert("wcsndup");
functionNames1_all.insert("wcspbrk");
functionNames1_all.insert("wcslen");
functionNames1_all.insert("wcsspn");
functionNames1_all.insert("wcsstr");
// cstdio
functionNames1_all.insert("fclose");
functionNames1_all.insert("feof");
@ -78,19 +103,27 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
functionNames1_all.insert("fseek");
functionNames1_all.insert("ftell");
functionNames1_all.insert("fputs");
functionNames1_all.insert("fputws");
functionNames1_all.insert("ferror");
functionNames1_all.insert("fgetc");
functionNames1_all.insert("fgetwc");
functionNames1_all.insert("fgetpos");
functionNames1_all.insert("fsetpos");
functionNames1_all.insert("freopen");
functionNames1_all.insert("fscanf");
functionNames1_all.insert("fprintf");
functionNames1_all.insert("fwscanf");
functionNames1_all.insert("fwprintf");
functionNames1_all.insert("fopen");
functionNames1_all.insert("rewind");
functionNames1_all.insert("printf");
functionNames1_all.insert("wprintf");
functionNames1_all.insert("scanf");
functionNames1_all.insert("wscanf");
functionNames1_all.insert("fscanf");
functionNames1_all.insert("sscanf");
functionNames1_all.insert("fwscanf");
functionNames1_all.insert("swscanf");
functionNames1_all.insert("setbuf");
functionNames1_all.insert("setvbuf");
functionNames1_all.insert("rename");
@ -113,6 +146,12 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
functionNames1_nullptr.insert("vprintf");
functionNames1_nullptr.insert("fprintf");
functionNames1_nullptr.insert("vfprintf");
functionNames1_nullptr.insert("wcscpy");
functionNames1_nullptr.insert("swprintf");
functionNames1_nullptr.insert("vswprintf");
functionNames1_nullptr.insert("vwprintf");
functionNames1_nullptr.insert("fwprintf");
functionNames1_nullptr.insert("vfwprintf");
functionNames1_nullptr.insert("fread");
functionNames1_nullptr.insert("gets");
functionNames1_nullptr.insert("gmtime");
@ -144,15 +183,35 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
functionNames2_all.insert("strspn");
functionNames2_all.insert("strstr");
functionNames2_all.insert("strxfrm");
functionNames2_all.insert("wcscat");
functionNames2_all.insert("wcsncat");
functionNames2_all.insert("wcscmp");
functionNames2_all.insert("wcsncmp");
functionNames2_all.insert("wcscoll");
functionNames2_all.insert("wcscpy");
functionNames2_all.insert("wcscspn");
functionNames2_all.insert("wcsncpy");
functionNames2_all.insert("wcspbrk");
functionNames2_all.insert("wcsspn");
functionNames2_all.insert("wcsstr");
functionNames2_all.insert("wcsxfrm");
functionNames2_all.insert("sprintf");
functionNames2_all.insert("fprintf");
functionNames2_all.insert("fscanf");
functionNames2_all.insert("sscanf");
functionNames2_all.insert("swprintf");
functionNames2_all.insert("fwprintf");
functionNames2_all.insert("fwscanf");
functionNames2_all.insert("swscanf");
functionNames2_all.insert("fputs");
functionNames2_all.insert("fputc");
functionNames2_all.insert("ungetc");
functionNames2_all.insert("fputws");
functionNames2_all.insert("fputwc");
functionNames2_all.insert("ungetwc");
functionNames2_all.insert("rename");
functionNames2_all.insert("putc");
functionNames2_all.insert("putwc");
functionNames2_all.insert("freopen");
functionNames2_nullptr.insert("frexp");
@ -187,21 +246,21 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
var.push_back(secondParam);
}
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf")) {
if (Token::Match(&tok, "printf|sprintf|snprintf|fprintf|fnprintf|scanf|sscanf|fscanf|wprintf|swprintf|fwprintf|wscanf|swscanf|fwscanf")) {
const Token* argListTok = 0; // Points to first va_list argument
std::string formatString;
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf");
bool scan = Token::Match(&tok, "scanf|sscanf|fscanf|wscanf|swscanf|fwscanf");
if (Token::Match(&tok, "printf|scanf ( %str%")) {
if (Token::Match(&tok, "printf|scanf|wprintf|wscanf ( %str%")) {
formatString = firstParam->strValue();
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<const Token *> 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);
}
}

View File

@ -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<unsigned int, const Token*>::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 Function*>::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) {

View File

@ -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;
}