Skip to content

Fix 11203: false positive: knownConditionTrueFalse 'always false' when comparing integer with floating-point#4350

Merged
danmar merged 5 commits intocppcheck-opensource:mainfrom
pfultz2:static-cast-float-2-int
Sep 8, 2022
Merged

Fix 11203: false positive: knownConditionTrueFalse 'always false' when comparing integer with floating-point#4350
danmar merged 5 commits intocppcheck-opensource:mainfrom
pfultz2:static-cast-float-2-int

Conversation

@pfultz2
Copy link
Copy Markdown
Contributor

@pfultz2 pfultz2 commented Aug 9, 2022

No description provided.

Comment thread cmake/dynamic_analyzer_options.cmake Outdated
if(ANALYZE_UNDEFINED)
# TODO: enable signed-integer-overflow
add_compile_options(-fsanitize=undefined -fsanitize=nullability -fno-sanitize=signed-integer-overflow)
add_compile_options(-fsanitize=undefined -fsanitize=nullability -fno-sanitize=signed-integer-overflow -fno-sanitize=float-cast-overflow)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide the UBSAN warning which is being reported here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is float-cast-overflow generated from the provided test case ? spontanously that sounds weird to me.

Copy link
Copy Markdown
Collaborator

@firewave firewave Aug 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html:

-fsanitize=float-cast-overflow: Conversion to, from, or between floating-point types which would overflow the destination. Because the range of representable values for all floating-point types supported by Clang is [-inf, +inf], the only cases detected are conversions from floating point to integer types.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. So we get a overflow when cppcheck analyze this code:

    check("void f() {\n"
          "    int i = 10;\n"
          "    if(i > 9.9){}\n"
          "    float f = 9.9f;\n"
          "    if(f < 10) {}\n"
          "}\n");

And therefore you have to disable that sanitizer? spontanously I am confused. Shouldn't our analysis be tweaked so the cast overflow is avoided?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder why the data flow thinks that some value is that large/small.. maybe it's some "impossible" value that needs to be casted better?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we get a overflow when cppcheck analyze this code

We dont get an overflow for that case. We get incorrect rounding. We get the overflow for this case:

void foo(double recoveredX) {
  for (double x = 1e-18; x < 1e40; x *= 1.9) {
    double relativeError = (x - recoveredX) / x;
  }
}

@firewave
Copy link
Copy Markdown
Collaborator

If this actually overflows should the overflow be more "controlled" so the result does not flip? Is this a case like https://trac.cppcheck.net/ticket/9994 where the value actually should be 128-bit?

Or even being reported as a finding?

Comment thread lib/valueflow.cpp
const double floatValue1 = value1.isFloatValue() ? value1.floatValue : value1.intvalue;
const double floatValue2 = value2.isFloatValue() ? value2.floatValue : value2.intvalue;
const MathLib::bigint intValue1 =
value1.isFloatValue() ? std::llround(value1.floatValue) : value1.intvalue;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention that UBSAN warning in comment that it is intentional.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt that the ubsan warning is intentional. if value1.floatValue is too large and we try to cast it to bigint.. what is the result? we don't want a random value for it right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if value1.floatValue is too large and we try to cast it to bigint.. what is the result? we don't want a random value for it right?

We dont actually use the value since one of the values is already float. I think we could make this lazy.

@pfultz2
Copy link
Copy Markdown
Contributor Author

pfultz2 commented Sep 6, 2022

I am no longer disabling UBSAN for this case.

@pfultz2
Copy link
Copy Markdown
Contributor Author

pfultz2 commented Sep 7, 2022

Anymow feedback on this?

@danmar danmar merged commit 7c986fb into cppcheck-opensource:main Sep 8, 2022
@pfultz2 pfultz2 deleted the static-cast-float-2-int branch September 20, 2022 05:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants