-
Notifications
You must be signed in to change notification settings - Fork 366
[clang][BoundsSafety][UBSan] Fix false-positive UBSan pointer overflow #12846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // RUN: %clang_cc1 -O0 -fbounds-safety -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - | FileCheck %s | ||
|
|
||
| #include <ptrcheck.h> | ||
|
|
||
| // Regression test for pointer subtraction generating a false-positive | ||
| // UBSan pointer overflow check when -fbounds-safety is enabled. | ||
| // The check must use the negated index so that (base - offset) ule base | ||
| // is checked, not (base + offset) ule base which is unconditionally false. | ||
| void ptr_sub(unsigned char * __bidi_indexable ptr, unsigned int offset) { | ||
| unsigned char * __bidi_indexable ptr2 = ptr - offset; | ||
| (void)ptr2; | ||
| } | ||
|
|
||
| // CHECK: %[[OFFSET:[a-z0-9]+]] = load i32 | ||
| // CHECK: %[[NEG:[a-z0-9.]+]] = sub i32 0, %[[OFFSET]] | ||
| // CHECK: getelementptr{{.*}} %[[NEG]] | ||
| // CHECK: %[[EXT:[a-z0-9.]+]] = sext i32 %[[NEG]] to i64 | ||
| // CHECK: call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %[[EXT]]) | ||
|
Comment on lines
+14
to
+18
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to use update_cc_test_checks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be a good idea so that this test is easier to update when upstream inevitably changes the IR.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this is an -O0 test, so the fragility is lower than the -O2 tests
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather keep this as is. I have not used that script in the past, but it is creating around 30 CHECK lines which I think is much more brittle than this. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm a little confused by this.
IsSubis already being passed to theIsSubtractionparameter ofEmitCheckedInBoundsGEPso the method knows we are doing a subtraction so it seems surprising that we would need to negateIdx.Are we passing the wrong value to the
SignedIndicesparameter ofEmitCheckedInBoundsGEP?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was pretty confused by this as well and looked at a number of callsites. Looking at the complete code you pasted above, it negates the index in the first case, does not in the second case (which might be a bug?). The last case is just a plain increment at least according to the comment.
I see the negation in other places as well.
SignedIndices is independent of this. For example in the test I wrote, SignedIndices = false and IsSub = true, while if i replace
ptr - offset;withptr - 3;SignedIndices = true and IsSub = false (which makes sense).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will double check this again and add some more tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that comment is misleading because
isSubtractionisbool isSubtraction = !isInc;on that path I think so this can still be a decrement.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That interesting. Sounds like when we have a constant we effectively are treating this as
ptr + (-3).I'm still very suspicious because given that we are telling
EmitCheckedInBoundsGEP:would suggest there isn't a need to negate the index at all. However a quick glance at the implementation shows:
It seems at least for the computed value we return, the
IsSubtractionisn't really used other than setting the wrapping flags. This makes it seem likeIsSubtractionis a bit of a footgun.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this seems to be bad API design, and fixing it would mean updating all the callsites. If you want I can create a radar and fix that upstream but we would also need a separate patch in this repo for bounds-safety usages. What would you recommend?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The origin of this seems to be from https://reviews.llvm.org/D34121.
So perhaps this is expected behavior because the doxygen comments say
and
IRBuilder::CreateInBoundsGEPdoesn't have any notion of subtraction. Everything is an addition and I think you have to manually negate any value in theIdxListfirst if you want to do negative indexing. Also becauseIdxListis a list and not a singlellvm::Value*which of those should be subtracted?That being said this is pretty confusing. I think we should at the least file an issue upstream and try to clean this up in a separate PR.
I don't want to block fixing the -fbounds-safety/ubsan bug on that though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh something to think about here too is how this interacts with
SanitizerKind::ArrayBoundsand if that expectsIdxto be negated or not.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep that also expects the index to be negated. I took a look at the code/few callsites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will update with more tests and resolve this conversation afterwards