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%") && isRefArg(tok->next()->varId()) && isAutoVar(tok->tokAt(4)->varId())) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(4)->varId()); if (checkRvalueExpression(var, tok->tokAt(5))) errorAutoVariableAssignment(tok->next(), false); } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)->varId()) && isAutoVar(tok->tokAt(5)->varId())) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()); if (checkRvalueExpression(var, tok->tokAt(6))) 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() && var1->isPointer()) { const Variable * var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(6)->varId()); if (isAutoVar(tok->tokAt(6)->varId()) && checkRvalueExpression(var2, tok->tokAt(7))) errorAutoVariableAssignment(tok->next(), true); } } 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() && var1->isPointer()) { if (isAutoVarArray(tok->tokAt(5)->varId())) errorAutoVariableAssignment(tok->next(), true); } } 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% * *")) { if (isAutoVarArray(tok->tokAt(4)->varId())) errorAutoVariableAssignment(tok->next(), false); } tok = tok->tokAt(4); } else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()->varId()) && isAutoVar(tok->linkAt(2)->tokAt(3)->varId())) { const Token* const varTok = tok->linkAt(2)->tokAt(3); const Variable * var = symbolDatabase->getVariableFromVarId(varTok->varId()); if (checkRvalueExpression(var, varTok->next())) 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% ) ;") || Token::Match(tok, "delete [| ]| (| %var% !![")) { tok = Token::findmatch(tok->next(), "%var%"); if (isAutoVarArray(tok->varId())) errorInvalidDeallocation(tok); } } } }
void CheckAutoVariables::autoVariables() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { // Critical assignment if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()) && isAutoVar(tok->tokAt(4))) { if (checkRvalueExpression(tok->tokAt(4))) errorAutoVariableAssignment(tok->next(), false); } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) { if (checkRvalueExpression(tok->tokAt(5))) 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 = tok->next()->variable(); if (var1 && var1->isArgument() && var1->isPointer()) { const Token * const var2tok = tok->tokAt(6); if (isAutoVar(var2tok) && checkRvalueExpression(var2tok)) errorAutoVariableAssignment(tok->next(), true); } } 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 = tok->next()->variable(); if (var1 && var1->isArgument() && var1->isPointer()) { if (isAutoVarArray(tok->tokAt(5))) errorAutoVariableAssignment(tok->next(), true); } } tok = tok->tokAt(5); } else if (Token::Match(tok, "[;{}] * %var% = %var% ;")) { const Variable * var1 = tok->tokAt(2)->variable(); if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-3), "%type% * *")) { if (isAutoVarArray(tok->tokAt(4))) errorAutoVariableAssignment(tok->next(), false); } tok = tok->tokAt(4); } else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) { const Token* const varTok = tok->linkAt(2)->tokAt(3); if (checkRvalueExpression(varTok)) errorAutoVariableAssignment(tok->next(), false); } // Critical return else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2))) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% [") && Token::simpleMatch(tok->linkAt(3), "] ;") && isAutoVarArray(tok->tokAt(2))) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) { const Variable * var1 = tok->tokAt(2)->variable(); if (var1 && var1->isArgument() && var1->typeEndToken()->str() != "&") errorReturnAddressOfFunctionParameter(tok, tok->strAt(2)); } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") || (_tokenizer->isCPP() && Token::Match(tok, "delete [| ]| (| %var% !!["))) { tok = Token::findmatch(tok->next(), "%var%"); if (isAutoVarArray(tok)) errorInvalidDeallocation(tok); } else if (Token::Match(tok, "free ( & %var% ) ;") || (_tokenizer->isCPP() && Token::Match(tok, "delete [| ]| (| & %var% !!["))) { tok = Token::findmatch(tok->next(), "%var%"); if (isAutoVar(tok)) errorInvalidDeallocation(tok); } } } }