From 7c0b011c0554710c0007ebdf6aca02202d09b09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 24 Jul 2019 16:17:52 +0200 Subject: [PATCH] Fixed #9230 (Improve check: integer conversion overflow in return) --- lib/checktype.cpp | 84 +++++++++++++++++++++++++++-------------------- lib/checktype.h | 2 ++ test/testtype.cpp | 5 +++ 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 1d35c56b8..e18aeceba 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -367,6 +367,7 @@ void CheckType::checkFloatToIntegerOverflow() vtint = tok->valueType(); vtfloat = tok->astOperand1()->valueType(); floatValues = &tok->astOperand1()->values(); + checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues); } // Assignment @@ -374,49 +375,60 @@ void CheckType::checkFloatToIntegerOverflow() vtint = tok->astOperand1()->valueType(); vtfloat = tok->astOperand2()->valueType(); floatValues = &tok->astOperand2()->values(); + checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues); } - // TODO: function call - - else - continue; - - // Conversion of float to integer? - if (!vtint || !vtint->isIntegral()) - continue; - if (!vtfloat || !vtfloat->isFloat()) - continue; - - for (const ValueFlow::Value &f : *floatValues) { - if (f.valueType != ValueFlow::Value::ValueType::FLOAT) - continue; - if (!mSettings->isEnabled(&f, false)) - continue; - if (f.floatValue > ~0ULL) - floatToIntegerOverflowError(tok, f); - else if ((-f.floatValue) > (1ULL<<62)) - floatToIntegerOverflowError(tok, f); - else if (mSettings->platformType != Settings::Unspecified) { - int bits = 0; - if (vtint->type == ValueType::Type::CHAR) - bits = mSettings->char_bit; - else if (vtint->type == ValueType::Type::SHORT) - bits = mSettings->short_bit; - else if (vtint->type == ValueType::Type::INT) - bits = mSettings->int_bit; - else if (vtint->type == ValueType::Type::LONG) - bits = mSettings->long_bit; - else if (vtint->type == ValueType::Type::LONGLONG) - bits = mSettings->long_long_bit; - else - continue; - if (bits < MathLib::bigint_bits && f.floatValue >= (((MathLib::biguint)1) << bits)) - floatToIntegerOverflowError(tok, f); + else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) { + const Scope *scope = tok->scope(); + while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction) + scope = scope->nestedIn; + if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) { + const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, mSettings); + vtfloat = tok->astOperand1()->valueType(); + floatValues = &tok->astOperand1()->values(); + checkFloatToIntegerOverflow(tok, &valueType, vtfloat, floatValues); } } } } +void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list *floatValues) +{ + // Conversion of float to integer? + if (!vtint || !vtint->isIntegral()) + return; + if (!vtfloat || !vtfloat->isFloat()) + return; + + for (const ValueFlow::Value &f : *floatValues) { + if (f.valueType != ValueFlow::Value::ValueType::FLOAT) + continue; + if (!mSettings->isEnabled(&f, false)) + continue; + if (f.floatValue > ~0ULL) + floatToIntegerOverflowError(tok, f); + else if ((-f.floatValue) > (1ULL<<62)) + floatToIntegerOverflowError(tok, f); + else if (mSettings->platformType != Settings::Unspecified) { + int bits = 0; + if (vtint->type == ValueType::Type::CHAR) + bits = mSettings->char_bit; + else if (vtint->type == ValueType::Type::SHORT) + bits = mSettings->short_bit; + else if (vtint->type == ValueType::Type::INT) + bits = mSettings->int_bit; + else if (vtint->type == ValueType::Type::LONG) + bits = mSettings->long_bit; + else if (vtint->type == ValueType::Type::LONGLONG) + bits = mSettings->long_long_bit; + else + continue; + if (bits < MathLib::bigint_bits && f.floatValue >= (((MathLib::biguint)1) << bits)) + floatToIntegerOverflowError(tok, f); + } + } +} + void CheckType::floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value) { std::ostringstream errmsg; diff --git a/lib/checktype.h b/lib/checktype.h index b786287b8..8caa51679 100644 --- a/lib/checktype.h +++ b/lib/checktype.h @@ -73,6 +73,8 @@ public: /** @brief %Check for float to integer overflow */ void checkFloatToIntegerOverflow(); + void checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list *floatValues); + private: // Error messages.. diff --git a/test/testtype.cpp b/test/testtype.cpp index 7beef12ac..c6e120442 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -318,6 +318,11 @@ private: " char c = 1234.5;\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); + + check("char f(void) {\n" + " return 1234.5;\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); } };