// default : bail out if the condition is has variable handling bool ExecutionPath::parseCondition(const Token &tok, std::list<ExecutionPath *> & checks) { unsigned int parlevel = 0; for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) { if (tok2->str() == "(") ++parlevel; else if (tok2->str() == ")") { if (parlevel == 0) break; --parlevel; } else if (Token::Match(tok2, "[;{}]")) break; if (tok2->varId() != 0) { bailOutVar(checks, tok2->varId()); } } for (std::list<ExecutionPath *>::iterator it = checks.begin(); it != checks.end();) { if ((*it)->varId > 0 && (*it)->numberOfIf >= 1) { delete *it; checks.erase(it++); } else { ++it; } } return false; }
/** parse tokens */ const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const { if (Token::Match(tok.previous(), "[;{}] const| struct| %type% * %var% ;")) { const Token * vartok = tok.tokAt(2); if (tok.str() == "const") vartok = vartok->next(); if (tok.str() == "struct") vartok = vartok->next(); if (vartok->varId() != 0) checks.push_back(new Nullpointer(owner, vartok->varId(), vartok->str())); return vartok->next(); } // Template pointer variable.. if (Token::Match(tok.previous(), "[;{}] %type% ::|<")) { const Token * vartok = &tok; while (Token::Match(vartok, "%type% ::")) vartok = vartok->tokAt(2); if (Token::Match(vartok, "%type% < %type%")) { vartok = vartok->tokAt(3); while (vartok && (vartok->str() == "*" || vartok->isName())) vartok = vartok->next(); } if (vartok && (vartok->str() == ">" || vartok->isName()) && Token::Match(vartok->next(), "* %var% ;|=")) { vartok = vartok->tokAt(2); checks.push_back(new Nullpointer(owner, vartok->varId(), vartok->str())); if (Token::simpleMatch(vartok->next(), "= 0 ;")) setnull(checks, vartok->varId()); return vartok->next(); } } if (Token::simpleMatch(&tok, "try {")) { // Bail out all used variables unsigned int indentlevel = 0; for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) { if (tok2->str() == "{") ++indentlevel; else if (tok2->str() == "}") { if (indentlevel == 0) break; if (indentlevel == 1 && !Token::simpleMatch(tok2,"} catch (")) return tok2; --indentlevel; } else if (tok2->varId()) bailOutVar(checks,tok2->varId()); } } if (Token::Match(&tok, "%var% (")) { if (tok.str() == "sizeof") return tok.next()->link(); // parse usage.. std::list<const Token *> var; CheckNullPointer::parseFunctionCall(tok, var, 0); for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) dereference(checks, *it); } else if (Token::simpleMatch(&tok, "( 0 &&")) return tok.link(); if (tok.varId() != 0) { // unknown : not really used. it is passed to isPointerDeRef. // if isPointerDeRef fails to determine if there // is a dereference the this will be set to true. bool unknown = false; if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;")) setnull(checks, tok.varId()); else if (CheckNullPointer::isPointerDeRef(&tok, unknown)) dereference(checks, &tok); else // TODO: Report debug warning that it's unknown if a // pointer is dereferenced bailOutVar(checks, tok.varId()); } else if (tok.str() == "delete") { const Token *ret = tok.next(); if (Token::simpleMatch(ret, "[ ]")) ret = ret->tokAt(2); if (Token::Match(ret, "%var% ;")) return ret->next(); } return &tok; }
/** parse tokens */ const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const { if (tok.varId() != 0) { // Pointer declaration declaration? if(symbolDatabase) { const Variable* var = symbolDatabase->getVariableFromVarId(tok.varId()); if (var && var->isPointer() && var->nameToken() == &tok) checks.push_back(new Nullpointer(owner, var->varId(), var->name(), symbolDatabase)); } } if (Token::simpleMatch(&tok, "try {")) { // Bail out all used variables const Token* tok2 = &tok; const Token* endtok = tok.linkAt(1); for (; tok2 && tok2 != endtok; tok2 = tok2->next()) { if (tok2->varId()) bailOutVar(checks,tok2->varId()); } return tok2; } if (Token::Match(&tok, "%var% (")) { if (tok.str() == "sizeof" || tok.str() == "typeid") return tok.next()->link(); // parse usage.. std::list<const Token *> var; CheckNullPointer::parseFunctionCall(tok, var, 0); for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) dereference(checks, *it); } else if (Token::simpleMatch(&tok, "( 0 &&")) return tok.link(); if (tok.varId() != 0) { // unknown: if isPointerDeRef fails to determine if there // is a dereference this will be set to true. bool unknown = owner->inconclusiveFlag(); bool deref = CheckNullPointer::isPointerDeRef(&tok, unknown, symbolDatabase); if (deref) dereference(checks, &tok); else if (unknown && owner->inconclusiveFlag()) dereference(checks, &tok); if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;")) setnull(checks, tok.varId()); else if (!deref && (!tok.previous()->isOp() || tok.previous()->str() == "&") && !tok.previous()->isAssignmentOp() && (!tok.next()->isOp() || tok.next()->str() == ">>")) bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out. } else if (tok.str() == "delete") { const Token *ret = tok.next(); if (Token::simpleMatch(ret, "[ ]")) ret = ret->tokAt(2); if (Token::Match(ret, "%var% ;")) return ret->next(); } else if (tok.str() == "return") { bool unknown = owner->inconclusiveFlag(); const Token* tok2 = &tok; for (; tok2 && tok2->str() != ";"; tok2 = tok2->next()) { if (tok2->varId()) { if (CheckNullPointer::isPointerDeRef(tok2, unknown, symbolDatabase) || unknown) dereference(checks, tok2); } // If return statement contains "?" then assume there // is no dangours dereferencing later if (tok2->str() == "?") { while (tok2 && tok2->str() != ";") tok2 = tok2->next(); return tok2; } } } return &tok; }