Skip to content

Commit 4ad32de

Browse files
authored
fix #11685: FP floatConversionOverflow from dead code (#6973)
1 parent 363a596 commit 4ad32de

File tree

6 files changed

+85
-2
lines changed

6 files changed

+85
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ $(libcppdir)/checkstl.o: lib/checkstl.cpp lib/addoninfo.h lib/astutils.h lib/che
573573
$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkstring.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
574574
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp
575575

576-
$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/check.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h
576+
$(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checktype.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h
577577
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp
578578

579579
$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checknullpointer.h lib/checkuninitvar.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h

lib/astutils.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,3 +3725,39 @@ bool isExhaustiveSwitch(const Token *startbrace)
37253725

37263726
return false;
37273727
}
3728+
3729+
bool isUnreachableOperand(const Token *tok)
3730+
{
3731+
for (;;)
3732+
{
3733+
const Token *parent = tok->astParent();
3734+
if (!parent)
3735+
break;
3736+
3737+
if (parent->isBinaryOp()) {
3738+
const bool left = tok == parent->astOperand1();
3739+
const Token *sibling = left ? parent->astOperand2() : parent->astOperand1();
3740+
3741+
// logical and
3742+
if (Token::simpleMatch(parent, "&&") && !left && sibling->hasKnownIntValue()
3743+
&& !sibling->getKnownIntValue())
3744+
return true;
3745+
3746+
// logical or
3747+
if (Token::simpleMatch(parent, "||") && !left && sibling->hasKnownIntValue()
3748+
&& sibling->getKnownIntValue())
3749+
return true;
3750+
3751+
// ternary
3752+
if (Token::simpleMatch(parent, ":") && Token::simpleMatch(parent->astParent(), "?")) {
3753+
const Token *condTok = parent->astParent()->astOperand1();
3754+
if (condTok->hasKnownIntValue() && static_cast<bool>(condTok->getKnownIntValue()) != left)
3755+
return true;
3756+
}
3757+
}
3758+
3759+
tok = parent;
3760+
}
3761+
3762+
return false;
3763+
}

lib/astutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,6 @@ bool isUnevaluated(const Token *tok);
448448

449449
bool isExhaustiveSwitch(const Token *startbrace);
450450

451+
bool isUnreachableOperand(const Token *tok);
452+
451453
#endif // astutilsH

lib/checktype.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//---------------------------------------------------------------------------
2121
#include "checktype.h"
2222

23+
#include "astutils.h"
2324
#include "errortypes.h"
2425
#include "mathlib.h"
2526
#include "platform.h"
@@ -437,19 +438,25 @@ void CheckType::checkFloatToIntegerOverflow()
437438

438439
// Explicit cast
439440
if (Token::Match(tok, "( %name%") && tok->astOperand1() && !tok->astOperand2()) {
441+
if (isUnreachableOperand(tok))
442+
continue;
440443
vtint = tok->valueType();
441444
vtfloat = tok->astOperand1()->valueType();
442445
checkFloatToIntegerOverflow(tok, vtint, vtfloat, tok->astOperand1()->values());
443446
}
444447

445448
// Assignment
446449
else if (tok->str() == "=" && tok->astOperand1() && tok->astOperand2()) {
450+
if (isUnreachableOperand(tok))
451+
continue;
447452
vtint = tok->astOperand1()->valueType();
448453
vtfloat = tok->astOperand2()->valueType();
449454
checkFloatToIntegerOverflow(tok, vtint, vtfloat, tok->astOperand2()->values());
450455
}
451456

452457
else if (tok->str() == "return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
458+
if (isUnreachableOperand(tok))
459+
continue;
453460
const Scope *scope = tok->scope();
454461
while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction)
455462
scope = scope->nestedIn;

oss-fuzz/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ $(libcppdir)/checkstl.o: ../lib/checkstl.cpp ../lib/addoninfo.h ../lib/astutils.
260260
$(libcppdir)/checkstring.o: ../lib/checkstring.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkstring.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h
261261
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkstring.cpp
262262

263-
$(libcppdir)/checktype.o: ../lib/checktype.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checktype.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h
263+
$(libcppdir)/checktype.o: ../lib/checktype.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checktype.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h
264264
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checktype.cpp
265265

266266
$(libcppdir)/checkuninitvar.o: ../lib/checkuninitvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checknullpointer.h ../lib/checkuninitvar.h ../lib/color.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h

test/testtype.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,44 @@ class TestType : public TestFixture {
495495
" return 1234.5;\n"
496496
"}", settingsDefault);
497497
ASSERT_EQUALS("[test.cpp:2]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str()));
498+
499+
checkP("#define TEST(b, f) b ? 5000 : (unsigned short)f\n" // #11685
500+
"void f()\n"
501+
"{\n"
502+
" unsigned short u = TEST(true, 75000.0);\n"
503+
"}\n", settingsDefault);
504+
ASSERT_EQUALS("", errout_str());
505+
506+
checkP("#define TEST(b, f) b ? 5000 : (unsigned short)f\n"
507+
"void f()\n"
508+
"{\n"
509+
" unsigned short u = TEST(false, 75000.0);\n"
510+
"}\n", settingsDefault);
511+
ASSERT_EQUALS("[test.cpp:4]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str()));
512+
513+
check( "bool f(unsigned short x);\n"
514+
"bool g() {\n"
515+
" return false && f((unsigned short)75000.0);\n"
516+
"}\n", settingsDefault);
517+
ASSERT_EQUALS("", errout_str());
518+
519+
check( "bool f(unsigned short x);\n"
520+
"bool g() {\n"
521+
" return true && f((unsigned short)75000.0);\n"
522+
"}\n", settingsDefault);
523+
ASSERT_EQUALS("[test.cpp:3]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str()));
524+
525+
check( "bool f(unsigned short x);\n"
526+
"bool g() {\n"
527+
" return true || f((unsigned short)75000.0);\n"
528+
"}\n", settingsDefault);
529+
ASSERT_EQUALS("", errout_str());
530+
531+
check( "bool f(unsigned short x);\n"
532+
"bool g() {\n"
533+
" return false || f((unsigned short)75000.0);\n"
534+
"}\n", settingsDefault);
535+
ASSERT_EQUALS("[test.cpp:3]: (error) Undefined behaviour: float () to integer conversion overflow.\n", removeFloat(errout_str()));
498536
}
499537

500538
void integerOverflow() { // #11794

0 commit comments

Comments
 (0)