-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Fix undefined behaviour in Array.cs #83116
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This creates an extra generic method instantiation. It should be ok - we are unlikely to hit this path for too many different Ts.
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 agree its typically fine when we can restrict the callers, but this is a general public API accessible to
Span<T>
and that can be hit for any user-definedT
.Given we've notably hit several aliasing bugs in the past for the JIT and had to fix them, including ones that caused invalid codegen, this seems like something we should generally be protecting against.
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.
3rd party code also notably looks to code in the BCL to see what it can and cannot do a lot of the time.
There are plenty of users that will see this code and copy it as is, not understanding the limitations or that they may need to fix it if the JIT ever changes.
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.
This code does address computation only, without dereferencing anything. The JIT should not run into any aliasing issues with it given the optimizations that it does today. In case the JIT starts doing more aggressive optimizations that depend on no aliasing, there are likely more issues to fix.
We have said many times that CoreLib is special and that it is not ok to copy code from it in general. If people copy code without understanding what it does and whether it is ok to copy it, it is their problem. I do not know how to help them.
I do not have a problem with taking this change. I am just saying that it does not make sense to fix all instances of this issue in CoreLib.
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 don't believe it has to. We had general bugs in
GetArrayDataReference
which is why the generic version was made intrinsic. The non-generic version has, afaik, the same general issue since it is not intrinsic yet today.For example we hit #79760 (comment) which was a fairly complex issue related to assertion prop and inlining caused by the aliasing of
T[]
toRawArrayData
. There were at least 3-4 other issues that were also caused by the general aliasing.In this case,
GetArrayDataReference
will still itself have a deref, because it's doingref Unsafe.As<RawData>(array).Data
and so a similar issue to the above can still occur.I think the only "fix" here is to ensure that such code is annotated with an explanation of why it is ok for corelib and not elsewhere. Even within the BCL team such knowledge is not always common place for these types of specialized scenarios and may end up in unintended places due to copy/paste, refactoring, etc.
Having a small code comment calling out something like "// DANGEROUS: Depends on runtime internals" is effectively a minimum safety net to help prevent these types of mistakes.
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 fixing the non-generic
GetArrayDataReference(Array)
to be intrinsic and may be another valid fix.Doing that would also notably remove one of the
Unsafe.As
generic instantiations.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.
Not true anymore since it was made an intrinsic.
This would work too, I didn't do it in my GADR PR though since I wasn't sure what nodes to emit there to handle both SZ and MD arrays.
Could you remind me what was the issue with making JIT intrinsics not cause instantiations when handled by the JIT?
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 meant memory writes. I believe that the aliasing bugs only occur with interleaving memory reads and writes given what the JIT can do today.
Non-generic GetArrayDataReference(Array) has to do more work to deal with MD arrays. We would have to do expansion of the non-generic GetArrayReference based on the actual type of the incoming argument to avoid the extra work for SD arrays.
#82917 (comment)