| 1688 | } |
| 1689 | |
| 1690 | void CheckConditionImpl::checkInvalidTestForOverflow() |
| 1691 | { |
| 1692 | // Interesting blogs: |
| 1693 | // https://www.airs.com/blog/archives/120 |
| 1694 | // https://kristerw.blogspot.com/2016/02/how-undefined-signed-overflow-enables.html |
| 1695 | // https://research.checkpoint.com/2020/optout-compiler-undefined-behavior-optimizations/ |
| 1696 | |
| 1697 | // x + c < x -> false |
| 1698 | // x + c <= x -> false |
| 1699 | // x + c > x -> true |
| 1700 | // x + c >= x -> true |
| 1701 | |
| 1702 | // x + y < x -> y < 0 |
| 1703 | |
| 1704 | |
| 1705 | if (!mSettings.severity.isEnabled(Severity::warning)) |
| 1706 | return; |
| 1707 | |
| 1708 | logChecker("CheckCondition::checkInvalidTestForOverflow"); // warning |
| 1709 | |
| 1710 | for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
| 1711 | if (!Token::Match(tok, "<|<=|>=|>") || !tok->isBinaryOp()) |
| 1712 | continue; |
| 1713 | |
| 1714 | const Token *lhsTokens[2] = {tok->astOperand1(), tok->astOperand2()}; |
| 1715 | for (const Token *lhs: lhsTokens) { |
| 1716 | std::string cmp = tok->str(); |
| 1717 | if (lhs == tok->astOperand2()) |
| 1718 | cmp[0] = (cmp[0] == '<') ? '>' : '<'; |
| 1719 | |
| 1720 | if (!Token::Match(lhs, "[+-]") || !lhs->isBinaryOp()) |
| 1721 | continue; |
| 1722 | |
| 1723 | const bool isSignedInteger = lhs->valueType() && lhs->valueType()->isIntegral() && lhs->valueType()->sign == ValueType::Sign::SIGNED; |
| 1724 | const bool isPointer = lhs->valueType() && lhs->valueType()->pointer > 0; |
| 1725 | if (!isSignedInteger && !isPointer) |
| 1726 | continue; |
| 1727 | |
| 1728 | const Token *exprTokens[2] = {lhs->astOperand1(), lhs->astOperand2()}; |
| 1729 | for (const Token *expr: exprTokens) { |
| 1730 | if (lhs->str() == "-" && expr == lhs->astOperand2()) |
| 1731 | continue; // TODO? |
| 1732 | |
| 1733 | if (expr->hasKnownIntValue()) |
| 1734 | continue; |
| 1735 | |
| 1736 | if (!isSameExpression(true, |
| 1737 | expr, |
| 1738 | lhs->astSibling(), |
| 1739 | mSettings, |
| 1740 | true, |
| 1741 | false)) |
| 1742 | continue; |
| 1743 | |
| 1744 | const Token * const other = expr->astSibling(); |
| 1745 | |
| 1746 | // x [+-] c cmp x |
| 1747 | if ((other->isNumber() && other->hasKnownIntValue() && other->getKnownIntValue() > 0) || |
no test coverage detected