checkFloatToIntegerOverflow: check all calculations, not only in function bodies
This commit is contained in:
parent
9268c2034a
commit
840c7eb258
|
@ -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<ValueFlow::Value> *floatValues;
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
const ValueType *vtint, *vtfloat;
|
||||
const std::list<ValueFlow::Value> *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<ValueFlow::Value>::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<ValueFlow::Value>::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue