Fixed #6350 (Tokenizer::simplifyCast: set Token::isCasted when cast is removed)

This commit is contained in:
Daniel Marjamäki 2014-12-23 16:16:14 +01:00
parent 95940ff0ef
commit 1b2a23b3fe
4 changed files with 37 additions and 13 deletions

View File

@ -841,7 +841,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
valueFlowCheckArrayIndex(tok->next(), arrayInfo);
}
else if (isPortabilityEnabled && tok->astParent() && tok->astParent()->str() == "+") {
else if (isPortabilityEnabled && !tok->isCasted() && tok->astParent() && tok->astParent()->str() == "+") {
const ValueFlow::Value *index;
if (tok == tok->astParent()->astOperand1())
index = tok->astParent()->astOperand2()->getMaxValue(false);

View File

@ -313,6 +313,12 @@ public:
void isExpandedMacro(bool m) {
setFlag(fIsExpandedMacro, m);
}
bool isCasted() const {
return getFlag(fIsCasted);
}
void isCasted(bool c) {
setFlag(fIsCasted, c);
}
bool isAttributeConstructor() const {
return getFlag(fIsAttributeConstructor);
}
@ -753,14 +759,15 @@ private:
fIsLong = (1 << 3),
fIsStandardType = (1 << 4),
fIsExpandedMacro = (1 << 5),
fIsAttributeConstructor = (1 << 6), // __attribute__((constructor)) __attribute__((constructor(priority)))
fIsAttributeDestructor = (1 << 7), // __attribute__((destructor)) __attribute__((destructor(priority)))
fIsAttributeUnused = (1 << 8), // __attribute__((unused))
fIsAttributePure = (1 << 9), // __attribute__((pure))
fIsAttributeConst = (1 << 10), // __attribute__((const))
fIsAttributeNothrow = (1 << 11), // __attribute__((nothrow))
fIsDeclspecNothrow = (1 << 12), // __declspec(nothrow)
fIsAttributeUsed = (1 << 13) // __attribute__((used))
fIsCasted = (1 << 6),
fIsAttributeConstructor = (1 << 7), // __attribute__((constructor)) __attribute__((constructor(priority)))
fIsAttributeDestructor = (1 << 8), // __attribute__((destructor)) __attribute__((destructor(priority)))
fIsAttributeUnused = (1 << 9), // __attribute__((unused))
fIsAttributePure = (1 << 10), // __attribute__((pure))
fIsAttributeConst = (1 << 11), // __attribute__((const))
fIsAttributeNothrow = (1 << 12), // __attribute__((nothrow))
fIsDeclspecNothrow = (1 << 13), // __declspec(nothrow)
fIsAttributeUsed = (1 << 14) // __attribute__((used))
};
unsigned int _flags;

View File

@ -5004,6 +5004,7 @@ void Tokenizer::simplifyCasts()
if (!tok->tokAt(2)->isUnsigned() && bits > 0)
bits--;
if (bits < 31 && value >= 0 && value < (1LL << bits)) {
tok->linkAt(1)->next()->isCasted(true);
Token::eraseTokens(tok, tok->next()->link()->next());
}
continue;
@ -5023,6 +5024,15 @@ void Tokenizer::simplifyCasts()
// Remove cast..
Token::eraseTokens(tok, tok->next()->link()->next());
// Set isCasted flag.
Token *tok2 = tok->next();
if (!Token::Match(tok2, "%var% [|."))
tok2->isCasted(true);
else {
// TODO: handle more complex expressions
tok2->next()->isCasted(true);
}
// Remove '* &'
if (Token::simpleMatch(tok, "* &")) {
tok->deleteNext();
@ -5038,6 +5048,7 @@ void Tokenizer::simplifyCasts()
// Replace pointer casts of 0.. "(char *)0" => "0"
while (Token::Match(tok->next(), "( %type% %type%| * ) 0")) {
tok->linkAt(1)->next()->isCasted(true);
Token::eraseTokens(tok, tok->next()->link()->next());
if (tok->str() == ")" && tok->link()->previous()) {
// If there was another cast before this, go back
@ -5048,11 +5059,11 @@ void Tokenizer::simplifyCasts()
if (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) {
Token *tok2 = tok->linkAt(2);
if (Token::simpleMatch(tok2, "> ("))
Token::eraseTokens(tok, tok2->next());
else
if (!Token::simpleMatch(tok2, "> ("))
break;
tok2->tokAt(2)->isCasted(true);
Token::eraseTokens(tok, tok2->next());
}
}
}

View File

@ -2955,6 +2955,12 @@ private:
" return a + 100;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
check("void f() {\n" // #6350 - fp when there is cast of buffer
" wchar_t buf[64];\n"
" p = (unsigned char *) buf + sizeof (buf);\n"
"}", false, "6350.c", false);
ASSERT_EQUALS("", errout.str());
}
void pointer_out_of_bounds_2() {