MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / checkForUnreleasedInputArgument

Method checkForUnreleasedInputArgument

lib/checkmemoryleak.cpp:1004–1079  ·  view source on GitHub ↗

--------------------------------------------------------------------------- Checks if an input argument to a function is the return value of an allocation function like malloc(), and the function does not release it. ---------------------------------------------------------------------------

Source from the content-addressed store, hash-verified

1002// like malloc(), and the function does not release it.
1003//---------------------------------------------------------------------------
1004void CheckMemoryLeakNoVarImpl::checkForUnreleasedInputArgument(const Scope *scope)
1005{
1006 // parse the executable scope until tok is reached...
1007 for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
1008 // allocating memory in parameter for function call..
1009 if (tok->varId() || !Token::Match(tok, "%name% ("))
1010 continue;
1011
1012 // check if the output of the function is assigned
1013 const Token* tok2 = tok->next()->astParent();
1014 while (tok2 && (tok2->isCast() || Token::Match(tok2, "?|:")))
1015 tok2 = tok2->astParent();
1016 const bool hasAssign = Token::Match(tok2, "%assign%");
1017 const bool hasReturn = Token::simpleMatch(tok->astTop(), "return");
1018
1019 const std::string& functionName = tok->str();
1020 if ((tok->isCpp() && functionName == "delete") ||
1021 functionName == "return")
1022 continue;
1023
1024 if (Token::simpleMatch(tok->next()->astParent(), "(")) // passed to another function
1025 continue;
1026 if (!tok->isKeyword() && !tok->function() && !mSettings.library.isLeakIgnore(functionName))
1027 continue;
1028
1029 if ((hasAssign || hasReturn) && !tok->function()) {
1030 const std::string& ret = mSettings.library.returnValueType(tok);
1031 if (ret.empty() || endsWith(ret, "*"))
1032 continue;
1033 }
1034
1035 const std::vector<const Token *> args = getArguments(tok);
1036 int argnr = -1;
1037 for (const Token* arg : args) {
1038 ++argnr;
1039 if (arg->isOp() && !(tok->isKeyword() && arg->str() == "*")) // e.g. switch (*new int)
1040 continue;
1041 while (arg->astOperand1()) {
1042 if (arg->isCpp() && Token::simpleMatch(arg, "new"))
1043 break;
1044 arg = arg->astOperand1();
1045 }
1046 const AllocType alloc = getAllocationType(arg, 0);
1047 if (alloc == No)
1048 continue;
1049 if (alloc == New || alloc == NewArray) {
1050 const Token* typeTok = arg->next();
1051 bool bail = !typeTok->isStandardType() &&
1052 (!typeTok->valueType() ||
1053 (typeTok->valueType()->type < ValueType::Type::SMART_POINTER &&
1054 typeTok->valueType()->type != ValueType::Type::POD)) &&
1055 !mSettings.library.detectContainerOrIterator(typeTok) &&
1056 !mSettings.library.podtype(typeTok->expressionString());
1057 if (bail && typeTok->type() && typeTok->type()->classScope &&
1058 typeTok->type()->classScope->numConstructors == 0 &&
1059 typeTok->type()->classScope->getDestructor() == nullptr) {
1060 bail = false;
1061 }

Callers

nothing calls this directly

Calls 15

nextMethod · 0.80
astParentMethod · 0.80
isCastMethod · 0.80
astTopMethod · 0.80
isLeakIgnoreMethod · 0.80
isOpMethod · 0.80
astOperand1Method · 0.80
typeMethod · 0.80
getDestructorMethod · 0.80
getArgumentVarMethod · 0.80
getSizeOfMethod · 0.80

Tested by

no test coverage detected