This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Fix handling of Max from getValueRange(...) in IntExprEvaluator::VisitCastExpr(...)
ClosedPublic

Authored by shafik on Jul 29 2022, 5:27 PM.

Details

Summary

This is a follow-up to D130058 to fix how we handle the Max value we obtain from getValueRange(...) in IntExprEvaluator::VisitCastExpr(...) which in the case of an enum that contains an enumerator with the max integer value will overflow by one.

The fix is to decrement the value of Max and use slt and ult for comparison Vs sle and ule.

getValueRange(...) is also used by CodeGenFunction::EmitScalarRangeCheck(...) through getRangeForType(...) and this code does generate the correct IR for these values even though it appears to be logically doing the same operations that does not work in IntExprEvaluator::VisitCastExpr(...).

Diff Detail

Event Timeline

shafik created this revision.Jul 29 2022, 5:27 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 29 2022, 5:27 PM
shafik requested review of this revision.Jul 29 2022, 5:27 PM

@thakis I created a PR for the fix to D130058 since I wanted to document this.

As long the pre-commit checks don't show anything off I will land this.

I added a test to also cover your case as well.

This revision was not accepted when it landed; it landed in state Needs Review.Jul 29 2022, 7:20 PM
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptJul 29 2022, 7:20 PM
erichkeane added inline comments.Aug 1 2022, 6:16 AM
clang/lib/AST/ExprConstant.cpp
13540

I don't think this is the correct answer. Even though the other use of this seems to 'work', getValueRange is still returning wrapped values here. The fix is to figure out how to fix the math in getValueRange, and change the sanitizer's IR generation if necessary.

shafik added inline comments.Aug 2 2022, 11:36 AM
clang/lib/AST/ExprConstant.cpp
13540

So the other user of these values is getRangeForLoadFromType(...) through getRangeForType(...) which is used to generate the range metadata and in this case the range is exclusive on the right side:

The pair a,b represents the range [a,b).

and it is allowed to wrap:

The range is allowed to wrap.

So I believe the behavior will be correct.

Even though the range looks off in this example: https://godbolt.org/z/z7d9PKoMn

!{i32 0, i32 -2147483648}

I think it does the right thing.

Note the language ref also says:

The type must match the type loaded by the instruction.

and a quick experiment to use i33 confirms this breaks.

erichkeane added inline comments.Aug 2 2022, 11:40 AM
clang/lib/AST/ExprConstant.cpp
13540

Hmm... ok. Well, its quite unfortunate that 2 of our 3 uses of this are having to hack around this behavior a bit, but I guess this will have to be acceptable short-term then.

shafik added inline comments.Aug 2 2022, 1:08 PM
clang/lib/AST/ExprConstant.cpp
13540

I agree, maybe getValueRange(...) needs a flag for inclusive Vs exclusive. That would remove the hack and make it explicit that we have a different requirement at the call site.