Fixed #9230 (Improve check: integer conversion overflow in return)

This commit is contained in:
Daniel Marjamäki 2019-07-24 16:17:52 +02:00
parent f29e88a8a5
commit 7c0b011c05
3 changed files with 55 additions and 36 deletions

View File

@ -367,6 +367,7 @@ void CheckType::checkFloatToIntegerOverflow()
vtint = tok->valueType(); vtint = tok->valueType();
vtfloat = tok->astOperand1()->valueType(); vtfloat = tok->astOperand1()->valueType();
floatValues = &tok->astOperand1()->values(); floatValues = &tok->astOperand1()->values();
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
} }
// Assignment // Assignment
@ -374,49 +375,60 @@ void CheckType::checkFloatToIntegerOverflow()
vtint = tok->astOperand1()->valueType(); vtint = tok->astOperand1()->valueType();
vtfloat = tok->astOperand2()->valueType(); vtfloat = tok->astOperand2()->valueType();
floatValues = &tok->astOperand2()->values(); floatValues = &tok->astOperand2()->values();
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
} }
// TODO: function call else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
const Scope *scope = tok->scope();
else while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction)
continue; scope = scope->nestedIn;
if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) {
// Conversion of float to integer? const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, mSettings);
if (!vtint || !vtint->isIntegral()) vtfloat = tok->astOperand1()->valueType();
continue; floatValues = &tok->astOperand1()->values();
if (!vtfloat || !vtfloat->isFloat()) checkFloatToIntegerOverflow(tok, &valueType, vtfloat, floatValues);
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);
} }
} }
} }
} }
void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *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) void CheckType::floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value)
{ {
std::ostringstream errmsg; std::ostringstream errmsg;

View File

@ -73,6 +73,8 @@ public:
/** @brief %Check for float to integer overflow */ /** @brief %Check for float to integer overflow */
void checkFloatToIntegerOverflow(); void checkFloatToIntegerOverflow();
void checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *floatValues);
private: private:
// Error messages.. // Error messages..

View File

@ -318,6 +318,11 @@ private:
" char c = 1234.5;\n" " char c = 1234.5;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str())); 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()));
} }
}; };