void CheckAutoVariables::autoVariables() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list<Scope>::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; unsigned int indentlevel = 0; for (const Token *tok = scope->classDef->next()->link(); tok; tok = tok->next()) { // indentlevel.. if (tok->str() == "{") ++indentlevel; else if (tok->str() == "}") { if (indentlevel <= 1) break; --indentlevel; } //Critical assignment if (Token::Match(tok, "[;{}] * %var% = & %var%") && errorAv(tok->tokAt(2), tok->tokAt(5))) { errorAutoVariableAssignment(tok); } else if (Token::Match(tok, "[;{}] %var% [ %any% ] = & %var%") && errorAv(tok->tokAt(1), tok->tokAt(7))) { errorAutoVariableAssignment(tok); } // Critical return else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2)->varId())) { reportError(tok, Severity::error, "autoVariables", "Return of the address of an auto-variable"); } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") && isAutoVarArray(tok->tokAt(2)->varId())) { reportError(tok, Severity::error, "autoVariables", "Invalid deallocation"); } } } }
void CheckAutoVariables::autoVariables() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list<Scope>::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { //Critical assignment if (Token::Match(tok, "[;{}] * %var% = & %var%") && errorAv(tok->tokAt(2), tok->tokAt(5))) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()); if (var && (!var->isClass() || var->type())) errorAutoVariableAssignment(tok->next(), false); } else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) { // TODO: check if the parameter is only changed temporarily (#2969) if (_settings->inconclusive) { const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId()); if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-2), "%type% *")) { const Variable * var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(6)->varId()); if (var2 && var2->isLocal() && !var2->isStatic() && !Token::simpleMatch(var2->typeEndToken(), "*")) errorAutoVariableAssignment(tok->next(), _settings->inconclusive); } } tok = tok->tokAt(6); } else if (Token::Match(tok, "[;{}] %var% . %var% = %var% ;")) { // TODO: check if the parameter is only changed temporarily (#2969) if (_settings->inconclusive) { const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId()); if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-2), "%type% *")) { const Variable * var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()); if (var2 && var2->isLocal() && var2->isArray() && !var2->isStatic()) errorAutoVariableAssignment(tok->next(), _settings->inconclusive); } } tok = tok->tokAt(5); } else if (Token::Match(tok, "[;{}] * %var% = %var% ;")) { const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-3), "%type% * *")) { const Variable * var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(4)->varId()); if (var2 && var2->isLocal() && var2->isArray() && !var2->isStatic()) errorAutoVariableAssignment(tok->next(), false); } tok = tok->tokAt(4); } else if (Token::Match(tok, "[;{}] %var% [ %any% ] = & %var%") && errorAv(tok->next(), tok->tokAt(7))) { errorAutoVariableAssignment(tok->next(), false); } // Critical return else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2)->varId())) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% [") && Token::simpleMatch(tok->linkAt(3), "] ;") && isAutoVarArray(tok->tokAt(2)->varId())) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) { const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); if (var1 && var1->isArgument() && var1->typeEndToken()->str() != "&") errorReturnAddressOfFunctionParameter(tok, tok->strAt(2)); } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") && isAutoVarArray(tok->tokAt(2)->varId())) { errorInvalidDeallocation(tok); } } } }
void CheckAutoVariables::autoVariables() { bool begin_function = false; bool begin_function_decl = false; int bindent = 0; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "%type% *|::| %var% (")) { begin_function = true; fp_list.clear(); vd_list.clear(); vda_list.clear(); } else if (begin_function && begin_function_decl && Token::Match(tok, "%type% * * %var%")) { fp_list.insert(tok->tokAt(3)->str()); } else if (begin_function && begin_function_decl && Token::Match(tok, "%type% * %var% [")) { fp_list.insert(tok->tokAt(2)->str()); } else if (begin_function && tok->str() == "(") { begin_function_decl = true; } else if (begin_function && tok->str() == ")") { begin_function_decl = false; } else if (begin_function && tok->str() == "{") { bindent++; } else if (begin_function && tok->str() == "}") { bindent--; } else if (bindent <= 0) { continue; } // Inside a function body if (Token::Match(tok, "%type% :: %any%") && !isExternOrStatic(tok)) { addVD(tok->tokAt(2)->varId()); } else if (Token::Match(tok, "%type% %var% [")) { addVDA(tok->next()->varId()); } else if (Token::Match(tok, "%var% %var% ;") && !isExternOrStatic(tok) && isTypeName(tok)) { addVD(tok->next()->varId()); } else if (Token::Match(tok, "const %var% %var% ;") && !isExternOrStatic(tok) && isTypeName(tok->next())) { addVD(tok->tokAt(2)->varId()); } //Critical assignment else if (Token::Match(tok, "[;{}] %var% = & %var%") && errorAv(tok->tokAt(1), tok->tokAt(4))) { errorAutoVariableAssignment(tok); } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && errorAv(tok->tokAt(2), tok->tokAt(5))) { errorAutoVariableAssignment(tok); } else if (Token::Match(tok, "[;{}] %var% [ %any% ] = & %var%") && errorAv(tok->tokAt(1), tok->tokAt(7))) { errorAutoVariableAssignment(tok); } // Critical return else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2)->varId())) { reportError(tok, Severity::error, "autoVariables", "Return of the address of an auto-variable"); } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") && isAutoVarArray(tok->tokAt(2)->varId())) { reportError(tok, Severity::error, "autoVariables", "Invalid deallocation"); } } vd_list.clear(); vda_list.clear(); fp_list.clear(); }