Integer overflow; generalized checking for nonportable code
This commit is contained in:
parent
01c434f8bf
commit
abd6c00c82
|
@ -20,6 +20,7 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include "checktype.h"
|
#include "checktype.h"
|
||||||
|
|
||||||
|
#include "astutils.h"
|
||||||
#include "mathlib.h"
|
#include "mathlib.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -229,6 +230,7 @@ void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &v
|
||||||
void CheckType::checkIntegerOverflowOptimisations()
|
void CheckType::checkIntegerOverflowOptimisations()
|
||||||
{
|
{
|
||||||
// Interesting blogs:
|
// Interesting blogs:
|
||||||
|
// https://www.airs.com/blog/archives/120
|
||||||
// https://kristerw.blogspot.com/2016/02/how-undefined-signed-overflow-enables.html
|
// https://kristerw.blogspot.com/2016/02/how-undefined-signed-overflow-enables.html
|
||||||
// https://research.checkpoint.com/2020/optout-compiler-undefined-behavior-optimizations/
|
// https://research.checkpoint.com/2020/optout-compiler-undefined-behavior-optimizations/
|
||||||
|
|
||||||
|
@ -247,20 +249,38 @@ void CheckType::checkIntegerOverflowOptimisations()
|
||||||
if (!Token::Match(tok, "<|<=|>=|>") || !tok->isBinaryOp())
|
if (!Token::Match(tok, "<|<=|>=|>") || !tok->isBinaryOp())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const std::string &cmp = tok->str();
|
const Token *lhsTokens[2] = {tok->astOperand1(), tok->astOperand2()};
|
||||||
const Token * const lhs = tok->astOperand1();
|
for (const Token *lhs: lhsTokens) {
|
||||||
|
std::string cmp = tok->str();
|
||||||
|
if (lhs == tok->astOperand2())
|
||||||
|
cmp[0] = (cmp[0] == '<') ? '>' : '<';
|
||||||
|
|
||||||
if (!Token::Match(lhs, "[+-]") || !lhs->isBinaryOp() || !lhs->valueType() || !lhs->valueType()->isIntegral() || lhs->valueType()->sign != ValueType::Sign::SIGNED)
|
if (!Token::Match(lhs, "[+-]") || !lhs->isBinaryOp() || !lhs->valueType() || !lhs->valueType()->isIntegral() || lhs->valueType()->sign != ValueType::Sign::SIGNED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token *expr = lhs->astOperand1();
|
const Token *exprTokens[2] = {lhs->astOperand1(), lhs->astOperand2()};
|
||||||
const Token *other = lhs->astOperand2();
|
for (const Token *expr: exprTokens) {
|
||||||
if (expr->varId() == 0 || expr->varId() != lhs->astSibling()->varId())
|
if (lhs->str() == "-" && expr == lhs->astOperand2())
|
||||||
|
continue; // TODO?
|
||||||
|
|
||||||
|
if (expr->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!isSameExpression(mTokenizer->isCPP(),
|
||||||
|
false,
|
||||||
|
expr,
|
||||||
|
lhs->astSibling(),
|
||||||
|
mSettings->library,
|
||||||
|
false,
|
||||||
|
false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Token * const other = expr->astSibling();
|
||||||
|
|
||||||
// x [+-] c cmp x
|
// x [+-] c cmp x
|
||||||
if (other->isNumber() && other->getKnownIntValue() > 0) {
|
if (other->isNumber() && other->getKnownIntValue() > 0) {
|
||||||
bool result;
|
bool result;
|
||||||
if (tok->astOperand1()->str() == "+")
|
if (lhs->str() == "+")
|
||||||
result = (cmp == ">" || cmp == ">=");
|
result = (cmp == ">" || cmp == ">=");
|
||||||
else
|
else
|
||||||
result = (cmp == "<" || cmp == "<=");
|
result = (cmp == "<" || cmp == "<=");
|
||||||
|
@ -281,6 +301,8 @@ void CheckType::checkIntegerOverflowOptimisations()
|
||||||
integerOverflowOptimisationError(tok, result);
|
integerOverflowOptimisationError(tok, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckType::integerOverflowOptimisationError(const Token *tok, const std::string &replace)
|
void CheckType::integerOverflowOptimisationError(const Token *tok, const std::string &replace)
|
||||||
|
|
Loading…
Reference in New Issue