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

Allow initonly field during ldflda and stfld import #57385

Merged
merged 1 commit into from
Aug 18, 2021

Conversation

am11
Copy link
Member

@am11 am11 commented Aug 14, 2021

Fixes #55033

An immediate fix for this issue could be:

--- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
+++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
@@ -2108,7 +2108,7 @@ void ImportAddressOfField(int token, bool isStatic)
                 instance = actualThis.Type;
 
                 if (field.IsInitOnly)
-                    Check(_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr, VerifierError.InitOnly);
+                    Check(_method.IsVirtual || (_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr), VerifierError.InitOnly);
             }
 
             Check(_method.OwningType.CanAccess(field, instance), VerifierError.FieldAccess);

in case of ToString, GetHashCode examples, we are:

  1. not in a constructor
  2. field's owning type is not the method owning type
  3. this is not a thisptr

However, reading the conversation in related thread dotnet/roslyn#22485, this check seems too conservative and does not take modern ECMA rules into account. This PR removes the check and adds +/- test cases where it should or shouldn't be allowed.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-Tools-ILVerification Issues related to ilverify tool and IL verification in general label Aug 14, 2021
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Aug 14, 2021
@ghost
Copy link

ghost commented Aug 14, 2021

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

Issue Details

Fixes #55033

An immediate fix for this issue could be:

--- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
+++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
@@ -2108,7 +2108,7 @@ void ImportAddressOfField(int token, bool isStatic)
                 instance = actualThis.Type;
 
                 if (field.IsInitOnly)
-                    Check(_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr, VerifierError.InitOnly);
+                    Check(_method.IsVirtual || (_method.IsConstructor && field.OwningType == _method.OwningType && actualThis.IsThisPtr), VerifierError.InitOnly);
             }
 
             Check(_method.OwningType.CanAccess(field, instance), VerifierError.FieldAccess);

in case of ToString, GetHashCode examples, we are:

  1. not in a constructor
  2. field's owning type is not the method owning type
  3. this is not a thisptr

However, reading the conversation in related thread dotnet/roslyn#22485, this check seems too conservative and does not take modern ECMA rules into account. This PR removes the check and adds +/- test cases where it should or shouldn't be allowed.

Author: am11
Assignees: -
Labels:

area-ILVerification

Milestone: -

@am11
Copy link
Member Author

am11 commented Aug 14, 2021

@jkotas, PTAL. I was able to reproduce it in tests using special. naming convention as specified in ilverify readme.

@am11 am11 force-pushed the feature/ilverify/relax-ldflda branch from 8383faf to 3fe6a7b Compare August 14, 2021 02:32
@jkotas
Copy link
Member

jkotas commented Aug 14, 2021

It would be better to add the verification rules for readonly references proposed in dotnet/designs#21 instead of just deleting this check. Have you thought about what it would take?

If it is not something you would like to spend time on right now, we should open a new issue on adding the verification rules for readonly references and comment out this check instead of deleting it, with the link to the new issue.

@jkotas
Copy link
Member

jkotas commented Aug 14, 2021

The same check for instance fields in ImportStoreField has this problem as well. It should get the same treatment. It will fail on C# program like this:

using System;

class Test
{
    public int MyProperty { get; init; }
    static void Main() { }
}

@am11
Copy link
Member Author

am11 commented Aug 15, 2021

The same check for instance fields in ImportStoreField has this problem as well.

I have updated stfld and stsfld checks such that:

  • specialname modreq(IsExternalInit) methods and .ctors of this type are allowed to modify initonly instance fields.
  • .cctors of this type are allowed to modify initonly static fields.

@am11
Copy link
Member Author

am11 commented Aug 15, 2021

It would be better to add the verification rules for readonly references proposed in dotnet/designs#21 instead of just deleting this check. Have you thought about what it would take?

Thanks for sharing this link. From the perspective of ldflda and ldsflda, the spec seem to have relaxed the rules for initonly fields. I have kept the checks commented for now.

@am11 am11 force-pushed the feature/ilverify/relax-ldflda branch from dd37909 to a63b014 Compare August 15, 2021 05:00
@am11 am11 changed the title Allow initonly fields during ldflda import Allow initonly field during ldflda and stfld import Aug 15, 2021
@am11 am11 force-pushed the feature/ilverify/relax-ldflda branch from a63b014 to 0d23e53 Compare August 15, 2021 12:41
// * `get_Property` -> [ 'get_Property' ]
// * `CheckSomething_Valid` -> [ 'CheckSomething', 'Valid' ]
// * 'WrongMethod_Invalid_BranchOutOfTry' -> [ 'WrongMethod', 'Invalid', 'BranchOutOfTry' ]
// * 'MoreWrongMethod_Invalid_TypeAccess.InitOnly' -> [ 'MoreWrongMethod', 'Invalid', 'TypeAccess', 'InitOnly' ]
Copy link
Member

Choose a reason for hiding this comment

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

TypeAccess.InitOnly

Should this be TypeAccess_InitOnly? I do not see where we are recognizing . as the separator.

Copy link
Member Author

Choose a reason for hiding this comment

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

We have 25 cases using period as a error code separator when there is more than one error:

$ git grep '_Invalid_.*\..*\(.*\)' ':/src/tests/ilverify/ILTests'

It is documented here https://github.com/dotnet/runtime/tree/main/src/coreclr/tools/ILVerify#methods-with-special-names. I agree it is quite complicated; imo, we should use xml or json list for this rather than complex naming convention parsing.

Copy link
Member

Choose a reason for hiding this comment

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

we should use xml or json list

Then you have a problem with the IL and json being out-of-sync all the time. I actually like the convention based scheme we have here.

Copy link
Member Author

@am11 am11 Aug 15, 2021

Choose a reason for hiding this comment

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

Then you have a problem with the IL and json being out-of-sync all the time.

Current approach is equally fragile. The test discovery does not give any indication whether or not it has skipped the test during parsing (which is spread across three separate methods of TestDataLoader.cs). We have to remember total count before and after the new additions.

@@ -95,19 +95,8 @@
ret
}

.method public hidebysig instance void 'special.StoreInitonlyFieldOtherInstance..ctor_Invalid_InitOnly'(class FieldTestsType c) cil managed { ret }
.method public hidebysig specialname rtspecialname instance void .ctor(class FieldTestsType c) cil managed
Copy link
Member

Choose a reason for hiding this comment

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

body is actually not doing what method name suggests.

As far as I can tell, StoreInitonlyFieldOtherInstance described well what the body was doing. Am I missing something?

@am11 am11 force-pushed the feature/ilverify/relax-ldflda branch 2 times, most recently from a74beaa to fc831d8 Compare August 15, 2021 17:23
@am11 am11 force-pushed the feature/ilverify/relax-ldflda branch from 75039cb to e66f149 Compare August 16, 2021 15:08
Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you!

@jkotas jkotas merged commit b7eb828 into dotnet:main Aug 18, 2021
@lovettchris
Copy link
Contributor

Thanks!

@am11 am11 deleted the feature/ilverify/relax-ldflda branch August 18, 2021 05:21
@ghost ghost locked as resolved and limited conversation to collaborators Sep 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Tools-ILVerification Issues related to ilverify tool and IL verification in general community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ILVerify: bug in verification of InitOnly fields
3 participants