#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();
|
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);
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue