#6786 segmentation fault (invalid code) in Tokenizer::simplifyRedundantParentheses. Small refactoring for Tokenizer::simplifyTokenList2() including additional calls to validate() - which prevents heap corruption on invalid code

This commit is contained in:
Alexander Mai 2015-06-24 20:22:28 +02:00
parent 9fedc9bd74
commit 6ba9c21fb9
3 changed files with 92 additions and 55 deletions

View File

@ -3661,52 +3661,7 @@ bool Tokenizer::simplifyTokenList2()
simplifyOffsetPointerDereference(); simplifyOffsetPointerDereference();
// Replace "&str[num]" => "(str + num)" // Replace "&str[num]" => "(str + num)"
std::set<unsigned int> pod; simplifyOffsetPointerReference();
for (const Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->isStandardType()) {
tok = tok->next();
while (tok && (tok->str() == "*" || tok->isName())) {
if (tok->varId() > 0) {
pod.insert(tok->varId());
break;
}
tok = tok->next();
}
if (!tok)
break;
}
}
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (!Token::Match(tok, "%num%|%name%|]|)") &&
(Token::Match(tok->next(), "& %name% [ %num%|%name% ] !!["))) {
tok = tok->next();
if (tok->next()->varId()) {
if (pod.find(tok->next()->varId()) == pod.end()) {
tok = tok->tokAt(5);
if (!tok) {
syntaxError(tok);
return false;
}
continue;
}
}
// '&' => '('
tok->str("(");
tok = tok->next();
// '[' => '+'
tok->deleteNext();
tok->insertToken("+");
tok = tok->tokAt(3);
//remove ']'
tok->str(")");
Token::createMutualLinks(tok->tokAt(-4), tok);
}
}
removeRedundantAssignment(); removeRedundantAssignment();
@ -3729,6 +3684,14 @@ bool Tokenizer::simplifyTokenList2()
simplifyIfAndWhileAssign(); // Could be affected by simplifyIfNot simplifyIfAndWhileAssign(); // Could be affected by simplifyIfNot
// replace strlen(str)
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "strlen ( %str% )")) {
tok->str(MathLib::toString(Token::getStrLength(tok->tokAt(2))));
tok->deleteNext(3);
}
}
bool modified = true; bool modified = true;
while (modified) { while (modified) {
if (_settings->terminated()) if (_settings->terminated())
@ -3738,22 +3701,16 @@ bool Tokenizer::simplifyTokenList2()
modified |= simplifyConditions(); modified |= simplifyConditions();
modified |= simplifyFunctionReturn(); modified |= simplifyFunctionReturn();
modified |= simplifyKnownVariables(); modified |= simplifyKnownVariables();
modified |= simplifyStrlen();
// replace strlen(str)
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "strlen ( %str% )")) {
tok->str(MathLib::toString(Token::getStrLength(tok->tokAt(2))));
tok->deleteNext(3);
modified = true;
}
}
modified |= removeRedundantConditions(); modified |= removeRedundantConditions();
modified |= simplifyRedundantParentheses(); modified |= simplifyRedundantParentheses();
modified |= simplifyConstTernaryOp(); modified |= simplifyConstTernaryOp();
modified |= simplifyCalculations(); modified |= simplifyCalculations();
validate();
} }
// simplify redundant loops // simplify redundant loops
simplifyWhile0(); simplifyWhile0();
removeRedundantFor(); removeRedundantFor();
@ -7312,6 +7269,55 @@ void Tokenizer::simplifyOffsetPointerDereference()
} }
} }
void Tokenizer::simplifyOffsetPointerReference()
{
std::set<unsigned int> pod;
for (const Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->isStandardType()) {
tok = tok->next();
while (tok && (tok->str() == "*" || tok->isName())) {
if (tok->varId() > 0) {
pod.insert(tok->varId());
break;
}
tok = tok->next();
}
if (!tok)
break;
}
}
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (!Token::Match(tok, "%num%|%name%|]|)") &&
(Token::Match(tok->next(), "& %name% [ %num%|%name% ] !!["))) {
tok = tok->next();
if (tok->next()->varId()) {
if (pod.find(tok->next()->varId()) == pod.end()) {
tok = tok->tokAt(5);
if (!tok) {
syntaxError(tok);
}
continue;
}
}
// '&' => '('
tok->str("(");
tok = tok->next();
// '[' => '+'
tok->deleteNext();
tok->insertToken("+");
tok = tok->tokAt(3);
//remove ']'
tok->str(")");
Token::createMutualLinks(tok->tokAt(-4), tok);
}
}
}
void Tokenizer::simplifyNestedStrcat() void Tokenizer::simplifyNestedStrcat()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
@ -10417,6 +10423,20 @@ void Tokenizer::simplifyMathExpressions()
} }
} }
bool Tokenizer::simplifyStrlen()
{
// replace strlen(str)
bool modified=false;
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "strlen ( %str% )")) {
tok->str(MathLib::toString(Token::getStrLength(tok->tokAt(2))));
tok->deleteNext(3);
modified=true;
}
}
return modified;
}
void Tokenizer::reportError(const Token* tok, const Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive) const void Tokenizer::reportError(const Token* tok, const Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive) const
{ {
const std::list<const Token*> callstack(1, tok); const std::list<const Token*> callstack(1, tok);

View File

@ -186,6 +186,12 @@ public:
*/ */
void simplifyOffsetPointerDereference(); void simplifyOffsetPointerDereference();
/**
* Simplify referencing a pointer offset:
* "Replace "&str[num]" => "(str + num)"
*/
void simplifyOffsetPointerReference();
/** Insert array size where it isn't given */ /** Insert array size where it isn't given */
void arraySize(); void arraySize();
@ -691,6 +697,12 @@ public:
*/ */
void simplifyDeprecated(); void simplifyDeprecated();
/**
* Replace strlen(str)
* @return true if any replacement took place, false else
* */
bool simplifyStrlen();
/** /**
* check for duplicate enum definition * check for duplicate enum definition
*/ */

View File

@ -127,6 +127,7 @@ private:
TEST_CASE(garbageCode85); TEST_CASE(garbageCode85);
TEST_CASE(garbageCode86); TEST_CASE(garbageCode86);
TEST_CASE(garbageCode87); TEST_CASE(garbageCode87);
TEST_CASE(garbageCode88);
TEST_CASE(garbageValueFlow); TEST_CASE(garbageValueFlow);
TEST_CASE(garbageSymbolDatabase); TEST_CASE(garbageSymbolDatabase);
@ -697,6 +698,10 @@ private:
ASSERT_THROW(checkCode("((X (128))) (int a) { v[ = {} (x 42) a] += }"), InternalError); // do not crash ASSERT_THROW(checkCode("((X (128))) (int a) { v[ = {} (x 42) a] += }"), InternalError); // do not crash
} }
void garbageCode88() { // #6786
ASSERT_THROW(checkCode("( ) { ( 0 ) { ( ) } } g ( ) { i( ( false ?) ( ) : 1 ) ; } ;"), InternalError); // do not crash
}
void garbageValueFlow() { void garbageValueFlow() {
// #6089 // #6089
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n" const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"