#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:
parent
9fedc9bd74
commit
6ba9c21fb9
130
lib/tokenize.cpp
130
lib/tokenize.cpp
|
@ -3661,52 +3661,7 @@ bool Tokenizer::simplifyTokenList2()
|
|||
simplifyOffsetPointerDereference();
|
||||
|
||||
// Replace "&str[num]" => "(str + num)"
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
simplifyOffsetPointerReference();
|
||||
|
||||
removeRedundantAssignment();
|
||||
|
||||
|
@ -3729,6 +3684,14 @@ bool Tokenizer::simplifyTokenList2()
|
|||
|
||||
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;
|
||||
while (modified) {
|
||||
if (_settings->terminated())
|
||||
|
@ -3738,22 +3701,16 @@ bool Tokenizer::simplifyTokenList2()
|
|||
modified |= simplifyConditions();
|
||||
modified |= simplifyFunctionReturn();
|
||||
modified |= simplifyKnownVariables();
|
||||
|
||||
// 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 |= simplifyStrlen();
|
||||
|
||||
modified |= removeRedundantConditions();
|
||||
modified |= simplifyRedundantParentheses();
|
||||
modified |= simplifyConstTernaryOp();
|
||||
modified |= simplifyCalculations();
|
||||
validate();
|
||||
}
|
||||
|
||||
|
||||
// simplify redundant loops
|
||||
simplifyWhile0();
|
||||
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()
|
||||
{
|
||||
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
|
||||
{
|
||||
const std::list<const Token*> callstack(1, tok);
|
||||
|
|
|
@ -186,6 +186,12 @@ public:
|
|||
*/
|
||||
void simplifyOffsetPointerDereference();
|
||||
|
||||
/**
|
||||
* Simplify referencing a pointer offset:
|
||||
* "Replace "&str[num]" => "(str + num)"
|
||||
*/
|
||||
void simplifyOffsetPointerReference();
|
||||
|
||||
/** Insert array size where it isn't given */
|
||||
void arraySize();
|
||||
|
||||
|
@ -691,6 +697,12 @@ public:
|
|||
*/
|
||||
void simplifyDeprecated();
|
||||
|
||||
/**
|
||||
* Replace strlen(str)
|
||||
* @return true if any replacement took place, false else
|
||||
* */
|
||||
bool simplifyStrlen();
|
||||
|
||||
/**
|
||||
* check for duplicate enum definition
|
||||
*/
|
||||
|
|
|
@ -127,6 +127,7 @@ private:
|
|||
TEST_CASE(garbageCode85);
|
||||
TEST_CASE(garbageCode86);
|
||||
TEST_CASE(garbageCode87);
|
||||
TEST_CASE(garbageCode88);
|
||||
|
||||
TEST_CASE(garbageValueFlow);
|
||||
TEST_CASE(garbageSymbolDatabase);
|
||||
|
@ -697,6 +698,10 @@ private:
|
|||
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() {
|
||||
// #6089
|
||||
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
||||
|
|
Loading…
Reference in New Issue