Fixed #9230 (Improve check: integer conversion overflow in return)
This commit is contained in:
parent
f29e88a8a5
commit
7c0b011c05
|
@ -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<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)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
|
|
|
@ -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<ValueFlow::Value> *floatValues);
|
||||
|
||||
private:
|
||||
|
||||
// Error messages..
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue