Пример #1
0
void CheckExceptionSafety::deallocThrow()
{
    if (!_settings->isEnabled("style"))
        return;

    const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();

    // Deallocate a global/member pointer and then throw exception
    // the pointer will be a dead pointer
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
        // only looking for delete now
        if (tok->str() != "delete")
            continue;

        // Check if this is something similar with: "delete p;"
        tok = tok->next();
        if (Token::simpleMatch(tok, "[ ]"))
            tok = tok->tokAt(2);
        if (!tok)
            break;
        if (!Token::Match(tok, "%var% ;"))
            continue;
        const unsigned int varid(tok->varId());
        if (varid == 0)
            continue;

        // we only look for global variables
        const Variable* var = symbolDatabase->getVariableFromVarId(varid);
        if (!var || !(var->isGlobal() || var->isStatic()))
            continue;

        // Token where throw occurs
        const Token *ThrowToken = 0;

        // is there a throw after the deallocation?
        const Token* const end2 = tok->scope()->classEnd;
        for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) {
            // Throw after delete -> Dead pointer
            if (tok2->str() == "throw") {
                if (_settings->inconclusive) { // For inconclusive checking, throw directly.
                    deallocThrowError(tok2, tok->str());
                    break;
                }
                ThrowToken = tok2;
            }

            // Variable is assigned -> Bail out
            else if (Token::Match(tok2, "%varid% =", varid)) {
                if (ThrowToken) // For non-inconclusive checking, wait until we find an assignement to it. Otherwise we assume it is safe to leave a dead pointer.
                    deallocThrowError(ThrowToken, tok2->str());
                break;
            }
            // Variable passed to function. Assume it becomes assigned -> Bail out
            else if (Token::Match(tok2, "[,(] &| %varid% [,)]", varid)) // TODO: No bailout if passed by value or as const reference
                break;
        }
    }
}
void CheckExceptionSafety::deallocThrow()
{
    const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();

    // Deallocate a global/member pointer and then throw exception
    // the pointer will be a dead pointer
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
        // only looking for delete now
        if (tok->str() != "delete")
            continue;

        // Check if this is something similar with: "delete p;"
        tok = tok->next();
        if (Token::simpleMatch(tok, "[ ]"))
            tok = tok->tokAt(2);
        if (!tok)
            break;
        if (!Token::Match(tok, "%var% ;"))
            continue;
        const unsigned int varid(tok->varId());
        if (varid == 0)
            continue;

        // we only look for global variables
        const Variable* var = symbolDatabase->getVariableFromVarId(varid);
        if (!var || !var->isGlobal())
            continue;

        // indentlevel..
        unsigned int indentlevel = 0;

        // Token where throw occurs
        const Token *ThrowToken = 0;

        // is there a throw after the deallocation?
        for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
            if (tok2->str() == "{")
                ++indentlevel;
            else if (tok2->str() == "}") {
                if (indentlevel == 0)
                    break;
                --indentlevel;
            }

            else if (tok2->str() == "throw")
                ThrowToken = tok2;

            // if the variable is not assigned after the throw then it
            // is assumed that it is not the intention that it is a dead pointer.
            else if (Token::Match(tok2, "%varid% =", varid)) {
                if (ThrowToken)
                    deallocThrowError(ThrowToken, tok->str());
                break;
            }
        }
    }
}
Пример #3
0
void CheckExceptionSafety::deallocThrow()
{
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
    {
        if (tok->str() != "delete")
            continue;

        // Check if this is something similar with: "delete p;"
        tok = tok->next();
        if (Token::simpleMatch(tok, "[ ]"))
            tok = tok->tokAt(2);
        if (!tok)
            break;
        if (!Token::Match(tok, "%var% ;"))
            continue;
        const unsigned int varid(tok->varId());
        if (varid == 0)
            continue;

        // is this variable a global variable?
        {
            bool globalVar = false;
            for (const Token *tok2 = _tokenizer->tokens(); tok2; tok2 = tok2->next())
            {
                if (tok->varId() == varid)
                {
                    globalVar = true;
                    break;
                }

                if (tok2->str() == "class")
                {
                    while (tok2 && tok2->str() != ";" && tok2->str() != "{")
                        tok2 = tok2->next();
                    tok2 = tok2 ? tok2->next() : 0;
                    if (!tok2)
                        break;
                }

                if (tok2->str() == "{")
                {
                    tok2 = tok2->link();
                    if (!tok2)
                        break;
                }
            }
            if (!globalVar)
                continue;
        }

        // is there a throw after the deallocation?
        unsigned int indentlevel = 0;
        const Token *ThrowToken = 0;
        for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
        {
            if (tok2->str() == "{")
                ++indentlevel;
            else if (tok2->str() == "}")
            {
                if (indentlevel == 0)
                    break;
                --indentlevel;
            }

            if (tok2->str() == "throw")
                ThrowToken = tok2;

            else if (Token::Match(tok2, "%varid% =", varid))
            {
                if (ThrowToken)
                    deallocThrowError(ThrowToken, tok->str());
                break;
            }
        }
    }
}