Skip to content

Commit 7c0b011

Browse files
committed
Fixed #9230 (Improve check: integer conversion overflow in return)
1 parent f29e88a commit 7c0b011

3 files changed

Lines changed: 50 additions & 31 deletions

File tree

lib/checktype.cpp

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -367,52 +367,64 @@ void CheckType::checkFloatToIntegerOverflow()
367367
vtint = tok->valueType();
368368
vtfloat = tok->astOperand1()->valueType();
369369
floatValues = &tok->astOperand1()->values();
370+
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
370371
}
371372

372373
// Assignment
373374
else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) {
374375
vtint = tok->astOperand1()->valueType();
375376
vtfloat = tok->astOperand2()->valueType();
376377
floatValues = &tok->astOperand2()->values();
378+
checkFloatToIntegerOverflow(tok, vtint, vtfloat, floatValues);
377379
}
378380

379-
// TODO: function call
381+
else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
382+
const Scope *scope = tok->scope();
383+
while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction)
384+
scope = scope->nestedIn;
385+
if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) {
386+
const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, mSettings);
387+
vtfloat = tok->astOperand1()->valueType();
388+
floatValues = &tok->astOperand1()->values();
389+
checkFloatToIntegerOverflow(tok, &valueType, vtfloat, floatValues);
390+
}
391+
}
392+
}
393+
}
380394

381-
else
382-
continue;
395+
void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *floatValues)
396+
{
397+
// Conversion of float to integer?
398+
if (!vtint || !vtint->isIntegral())
399+
return;
400+
if (!vtfloat || !vtfloat->isFloat())
401+
return;
383402

384-
// Conversion of float to integer?
385-
if (!vtint || !vtint->isIntegral())
403+
for (const ValueFlow::Value &f : *floatValues) {
404+
if (f.valueType != ValueFlow::Value::ValueType::FLOAT)
386405
continue;
387-
if (!vtfloat || !vtfloat->isFloat())
406+
if (!mSettings->isEnabled(&f, false))
388407
continue;
389-
390-
for (const ValueFlow::Value &f : *floatValues) {
391-
if (f.valueType != ValueFlow::Value::ValueType::FLOAT)
408+
if (f.floatValue > ~0ULL)
409+
floatToIntegerOverflowError(tok, f);
410+
else if ((-f.floatValue) > (1ULL<<62))
411+
floatToIntegerOverflowError(tok, f);
412+
else if (mSettings->platformType != Settings::Unspecified) {
413+
int bits = 0;
414+
if (vtint->type == ValueType::Type::CHAR)
415+
bits = mSettings->char_bit;
416+
else if (vtint->type == ValueType::Type::SHORT)
417+
bits = mSettings->short_bit;
418+
else if (vtint->type == ValueType::Type::INT)
419+
bits = mSettings->int_bit;
420+
else if (vtint->type == ValueType::Type::LONG)
421+
bits = mSettings->long_bit;
422+
else if (vtint->type == ValueType::Type::LONGLONG)
423+
bits = mSettings->long_long_bit;
424+
else
392425
continue;
393-
if (!mSettings->isEnabled(&f, false))
394-
continue;
395-
if (f.floatValue > ~0ULL)
396-
floatToIntegerOverflowError(tok, f);
397-
else if ((-f.floatValue) > (1ULL<<62))
426+
if (bits < MathLib::bigint_bits && f.floatValue >= (((MathLib::biguint)1) << bits))
398427
floatToIntegerOverflowError(tok, f);
399-
else if (mSettings->platformType != Settings::Unspecified) {
400-
int bits = 0;
401-
if (vtint->type == ValueType::Type::CHAR)
402-
bits = mSettings->char_bit;
403-
else if (vtint->type == ValueType::Type::SHORT)
404-
bits = mSettings->short_bit;
405-
else if (vtint->type == ValueType::Type::INT)
406-
bits = mSettings->int_bit;
407-
else if (vtint->type == ValueType::Type::LONG)
408-
bits = mSettings->long_bit;
409-
else if (vtint->type == ValueType::Type::LONGLONG)
410-
bits = mSettings->long_long_bit;
411-
else
412-
continue;
413-
if (bits < MathLib::bigint_bits && f.floatValue >= (((MathLib::biguint)1) << bits))
414-
floatToIntegerOverflowError(tok, f);
415-
}
416428
}
417429
}
418430
}

lib/checktype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class CPPCHECKLIB CheckType : public Check {
7373

7474
/** @brief %Check for float to integer overflow */
7575
void checkFloatToIntegerOverflow();
76+
void checkFloatToIntegerOverflow(const Token *tok, const ValueType *vtint, const ValueType *vtfloat, const std::list<ValueFlow::Value> *floatValues);
77+
7678
private:
7779

7880
// Error messages..

test/testtype.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ class TestType : public TestFixture {
318318
" char c = 1234.5;\n"
319319
"}");
320320
ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str()));
321+
322+
check("char f(void) {\n"
323+
" return 1234.5;\n"
324+
"}");
325+
ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout.str()));
321326
}
322327
};
323328

0 commit comments

Comments
 (0)