From 840c7eb25814a804734794a2872c3c94b233a8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 19 Sep 2017 19:30:24 +0200 Subject: [PATCH] checkFloatToIntegerOverflow: check all calculations, not only in function bodies --- lib/checktype.cpp | 97 ++++++++++++++++++++++------------------------- test/testtype.cpp | 7 +++- 2 files changed, 51 insertions(+), 53 deletions(-) diff --git a/lib/checktype.cpp b/lib/checktype.cpp index e34e3e0fc..66f8b6ae3 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -344,65 +344,60 @@ void CheckType::longCastReturnError(const Token *tok) void CheckType::checkFloatToIntegerOverflow() { - const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); - const std::size_t functions = symbolDatabase->functionScopes.size(); - for (std::size_t i = 0; i < functions; ++i) { - const Scope * scope = symbolDatabase->functionScopes[i]; - for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { - const ValueType *vtint, *vtfloat; - const std::list *floatValues; + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { + const ValueType *vtint, *vtfloat; + const std::list *floatValues; - // Explicit cast - if (Token::Match(tok, "( %name%") && tok->astOperand1() && !tok->astOperand2()) { - vtint = tok->valueType(); - vtfloat = tok->astOperand1()->valueType(); - floatValues = &tok->astOperand1()->values(); - } + // Explicit cast + if (Token::Match(tok, "( %name%") && tok->astOperand1() && !tok->astOperand2()) { + vtint = tok->valueType(); + vtfloat = tok->astOperand1()->valueType(); + floatValues = &tok->astOperand1()->values(); + } - // Assignment - else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) { - vtint = tok->astOperand1()->valueType(); - vtfloat = tok->astOperand2()->valueType(); - floatValues = &tok->astOperand2()->values(); - } + // Assignment + else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) { + vtint = tok->astOperand1()->valueType(); + vtfloat = tok->astOperand2()->valueType(); + floatValues = &tok->astOperand2()->values(); + } - // TODO: function call + // TODO: function call - else + else + continue; + + // Conversion of float to integer? + if (!vtint || !vtint->isIntegral()) + continue; + if (!vtfloat || !vtfloat->isFloat()) + continue; + + for (std::list::const_iterator it = floatValues->begin(); it != floatValues->end(); ++it) { + if (it->valueType != ValueFlow::Value::FLOAT) continue; - - // Conversion of float to integer? - if (!vtint || !vtint->isIntegral()) + if (!_settings->isEnabled(&(*it), false)) continue; - if (!vtfloat || !vtfloat->isFloat()) - continue; - - for (std::list::const_iterator it = floatValues->begin(); it != floatValues->end(); ++it) { - if (it->valueType != ValueFlow::Value::FLOAT) + if (it->floatValue > ~0ULL) + floatToIntegerOverflowError(tok, *it); + else if ((-it->floatValue) > (1ULL<<62)) + floatToIntegerOverflowError(tok, *it); + else if (_settings->platformType != Settings::Unspecified) { + int bits = 0; + if (vtint->type == ValueType::Type::CHAR) + bits = _settings->char_bit; + else if (vtint->type == ValueType::Type::SHORT) + bits = _settings->short_bit; + else if (vtint->type == ValueType::Type::INT) + bits = _settings->int_bit; + else if (vtint->type == ValueType::Type::LONG) + bits = _settings->long_bit; + else if (vtint->type == ValueType::Type::LONGLONG) + bits = _settings->long_long_bit; + else continue; - if (!_settings->isEnabled(&(*it), false)) - continue; - if (it->floatValue > ~0ULL) + if (bits < 64 && it->floatValue >= (1ULL << bits)) floatToIntegerOverflowError(tok, *it); - else if ((-it->floatValue) > (1ULL<<62)) - floatToIntegerOverflowError(tok, *it); - else if (_settings->platformType != Settings::Unspecified) { - int bits = 0; - if (vtint->type == ValueType::Type::CHAR) - bits = _settings->char_bit; - else if (vtint->type == ValueType::Type::SHORT) - bits = _settings->short_bit; - else if (vtint->type == ValueType::Type::INT) - bits = _settings->int_bit; - else if (vtint->type == ValueType::Type::LONG) - bits = _settings->long_bit; - else if (vtint->type == ValueType::Type::LONGLONG) - bits = _settings->long_long_bit; - else - continue; - if (bits < 64 && it->floatValue >= (1ULL << bits)) - floatToIntegerOverflowError(tok, *it); - } } } } diff --git a/test/testtype.cpp b/test/testtype.cpp index ca300a60e..88b62b88a 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -148,9 +148,9 @@ private: } void signConversion() { - check("x = -4 * (unsigned)y;"); + check("x = -4 * (unsigned)y;"); ASSERT_EQUALS("[test.cpp:1]: (warning) Suspicious code: sign conversion of -4 in calculation because '-4' has a negative value\n", errout.str()); - + check("unsigned int f1(signed int x, unsigned int y) {" // x is signed " return x * y;\n" "}\n" @@ -235,6 +235,9 @@ private: } void checkFloatToIntegerOverflow() { + check("x = (int)1E100;"); + ASSERT_EQUALS("[test.cpp:1]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); + check("void f(void) {\n" " return (int)1E100;\n" "}\n");