//--------------------------------------------------------------------------- // memset(p, y, 0 /* bytes to fill */) <- 2nd and 3rd arguments inverted //--------------------------------------------------------------------------- void CheckFunctions::memsetZeroBytes() { // FIXME: // Replace this with library configuration. // For instance: // <arg nr="3"> // <warn knownIntValue="0" severity="warning" msg="..."/> // </arg> if (!_settings->isEnabled(Settings::WARNING)) return; 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->next(); tok != scope->classEnd; tok = tok->next()) { if (Token::Match(tok, "memset|wmemset (") && (numberOfArguments(tok)==3)) { const std::vector<const Token *> &arguments = getArguments(tok); if (WRONG_DATA(arguments.size() != 3U, tok)) continue; const Token* lastParamTok = arguments[2]; if (lastParamTok->str() == "0") memsetZeroBytesError(tok); } } } }
bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive) { if (!tok) return false; // address of variable const bool addressOf = Token::simpleMatch(tok->previous(), "&"); // passing variable to subfunction? if (Token::Match(tok->tokAt(-2), ") & %name% [,)]") && Token::Match(tok->linkAt(-2)->previous(), "[,(] (")) ; else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[(,] &| %name% [,)]")) ; else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[?:] &| %name% [:,)]")) { const Token *parent = tok->astParent(); if (parent == tok->previous() && parent->str() == "&") parent = parent->astParent(); while (Token::Match(parent, "[?:]")) parent = parent->astParent(); while (Token::simpleMatch(parent, ",")) parent = parent->astParent(); if (!parent || parent->str() != "(") return false; } else return false; // reinterpret_cast etc.. if (Token::Match(tok->tokAt(-3), "> ( & %name% ) [,)]") && tok->linkAt(-3) && Token::Match(tok->linkAt(-3)->tokAt(-2), "[,(] %type% <")) tok = tok->linkAt(-3); // goto start of function call and get argnr unsigned int argnr = 0; while (tok && tok->str() != "(") { if (tok->str() == ",") ++argnr; else if (tok->str() == ")") tok = tok->link(); tok = tok->previous(); } tok = tok ? tok->previous() : nullptr; if (tok && tok->link() && tok->str() == ">") tok = tok->link()->previous(); if (!Token::Match(tok, "%name% [(<]")) return false; // not a function => variable not changed // Constructor call if (tok->variable() && tok->variable()->nameToken() == tok) { // Find constructor.. const unsigned int argCount = numberOfArguments(tok); const Scope *typeScope = tok->variable()->typeScope(); if (typeScope) { for (std::list<Function>::const_iterator it = typeScope->functionList.begin(); it != typeScope->functionList.end(); ++it) { if (!it->isConstructor() || it->argCount() < argCount) continue; const Variable *arg = it->getArgumentVar(argnr); if (arg && arg->isReference() && !arg->isConst()) return true; } return false; } if (inconclusive) *inconclusive = true; return false; } if (!tok->function()) { // if the library says 0 is invalid // => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic) if (!addressOf && settings && settings->library.isnullargbad(tok, 1+argnr)) return false; // addressOf => inconclusive if (!addressOf) { if (inconclusive != nullptr) *inconclusive = true; return false; } return true; } const Variable *arg = tok->function()->getArgumentVar(argnr); if (addressOf) { if (!(arg && arg->isConst())) return true; // If const is applied to the pointer, then the value can still be modified if (arg && Token::simpleMatch(arg->typeEndToken(), "* const")) return true; } return arg && !arg->isConst() && arg->isReference(); }