Integer overflow; generalized checking for nonportable code

This commit is contained in:
Daniel Marjamäki 2021-01-04 19:43:05 +01:00
parent 01c434f8bf
commit abd6c00c82
1 changed files with 50 additions and 28 deletions

View File

@ -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)