Skip to content
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

System.Linq.Expressions simulating Nullable.GetValueOrDefault should use GetUninitializedObject instead of Activator.CreateInstance #47647

Closed
eerhardt opened this issue Jan 29, 2021 · 4 comments
Labels
area-System.Linq.Expressions untriaged New issue has not been triaged by the area owner

Comments

@eerhardt
Copy link
Member

See the conversation here.

This code in SLE:

public override int Run(InterpretedFrame frame)
{
if (frame.Peek() == null)
{
frame.Pop();
frame.Push(Activator.CreateInstance(_defaultValueType));

has the possibility of behaving incorrectly if/when dotnet/csharplang#99 is implemented in the future. If the value type has a parameterless constructor present in IL, Activator.CreateInstance would run that parameterless constructor. Which means the value you get back from Nullable<T>.GetValueOrDefault() could be different if run through this code than if you actually called Nullable<T>.GetValueOrDefault() on a "null" value.

We should instead change this to use GetUninitializedObject which wouldn't run the parameterless constructor. (And of course add a test for this.)

@ghost
Copy link

ghost commented Jan 29, 2021

Tagging subscribers to this area: @cston
See info in area-owners.md if you want to be subscribed.

Issue Details

See the conversation here.

This code in SLE:

public override int Run(InterpretedFrame frame)
{
if (frame.Peek() == null)
{
frame.Pop();
frame.Push(Activator.CreateInstance(_defaultValueType));

has the possibility of behaving incorrectly if/when dotnet/csharplang#99 is implemented in the future. If the value type has a parameterless constructor present in IL, Activator.CreateInstance would run that parameterless constructor. Which means the value you get back from Nullable<T>.GetValueOrDefault() could be different if run through this code than if you actually called Nullable<T>.GetValueOrDefault() on a "null" value.

We should instead change this to use GetUninitializedObject which wouldn't run the parameterless constructor. (And of course add a test for this.)

Author: eerhardt
Assignees: -
Labels:

area-System.Linq.Expressions

Milestone: -

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jan 29, 2021
@GrabYourPitchforks
Copy link
Member

See also the table I put in the description of #45397. It gives a few other scenarios where LINQ instantiates objects incorrectly.

@eerhardt
Copy link
Member Author

eerhardt commented Feb 1, 2021

If this call isn't changed to GetUninitializedObject, we need to revisit the suppression being added here:

https://github.com/dotnet/runtime/pull/47585/files/07c0fc14fbab9b092a2270083bd933cbee8b2248#r567222530

@eerhardt
Copy link
Member Author

eerhardt commented Feb 3, 2021

Closing in favor of #45397. There are a handful of scenarios that need fixing here, it doesn't make sense to track each scenario in a separate issue.

@eerhardt eerhardt closed this as completed Feb 3, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Mar 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Linq.Expressions untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

2 participants