Fix ILVerify false positive: ReturnPtrToStack on by-value return of a ref struct#129032
Fix ILVerify false positive: ReturnPtrToStack on by-value return of a ref struct#129032Copilot wants to merge 4 commits into
Conversation
|
Tagging subscribers to this area: @agocke |
…returns Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
| } | ||
|
|
||
| // Returning a ref struct by value (IsByRefLike) should be valid. | ||
| // This was a false positive: ILVerify incorrectly reported ReturnPtrToStack. |
There was a problem hiding this comment.
| // This was a false positive: ILVerify incorrectly reported ReturnPtrToStack. |
|
@copilot address my feedback Also, address the "The other side of the bug is in" part of the original bug report |
…ome fix Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Addressed in the latest commit. The "other side of the bug" fix (
|
There was a problem hiding this comment.
Pull request overview
This PR updates the ILVerification importer’s tracking of PermanentHome to address a ReturnPtrToStack false positive when returning a ref struct (IsByRefLike) by value, and adds IL tests covering the scenario.
Changes:
- Mark stack values produced by
ldloc/ldargasPermanentHome(viaImportLoadVar), intended to allow by-value ref struct returns to pass verification. - Relax
StackValue.SetIsPermanentHome()to be callable on non-ByRefstack kinds. - Add new IL test cases for returning a ref struct by value (valid) and returning a byref to a ref struct field (invalid).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/coreclr/tools/ILVerification/ILImporter.Verify.cs | Changes ImportLoadVar to set PermanentHome on loaded variables. |
| src/coreclr/tools/ILVerification/ILImporter.StackValue.cs | Removes Debug.Assert(Kind == StackValueKind.ByRef) from SetIsPermanentHome(). |
| src/coreclr/tools/ILVerification.Tests/ILTests/ReturnTests.il | Adds a ref struct IL type and two return-related test methods. |
| var stackValue = StackValue.CreateFromType(varType); | ||
| stackValue.SetIsPermanentHome(); | ||
| if (index == 0 && argument && _thisType != null) |
ILVerify incorrectly reports
ReturnPtrToStackwhen a method returns anIsByRefLike(ref struct) type by value. The check atImportReturnapplied theIsPermanentHomerequirement for anyIsByRefLikereturn type, butIsPermanentHomeis only meaningful when the stack holds aByRef—not when it holds a value-type.Root cause
The
ImportReturncheck treatedIsByRefLikeandIsByRefidentically, requiringIsPermanentHomeon the stack value. For by-value ref struct returns, the stack holds aValueType-kind entry (fromldloc/ldarg), not aByRef, soIsPermanentHomewas alwaysfalse— incorrectly triggering the error.Additionally,
ImportLoadVarnever calledSetIsPermanentHome()on the stack value it pushed, even though locals and arguments are permanent homes for the lifetime of the method.Fix
ILImporter.StackValue.cs: Removed theDebug.Assert(Kind == StackValueKind.ByRef)guard fromSetIsPermanentHome, allowing it to be called on value-type stack entries.ILImporter.Verify.cs/ImportLoadVar: AddedstackValue.SetIsPermanentHome()— stack values loaded from locals and arguments are always permanent homes.With this in place, the
ImportReturncheck remains in its original simple form:A
ldloc/ldargof a ref struct now carriesIsPermanentHome = true, so the check correctly passes for by-value returns. Returning abyrefto a local/arg (e.g.ldarga.s; ret) still correctly fails, asImportAddressOfVardoes not setIsPermanentHome.Tests
Added to
ReturnTests.il:Return.RefStructByValue_Valid—ldarg; stloc; ldloc; retof a ref struct passes verificationReturn.LocalRefStructFieldByRef_Invalid_ReturnPtrToStack— returning abyrefto a field of a local ref struct argument is correctly rejected