Skip to content

Conversation

@stakx
Copy link
Member

@stakx stakx commented Sep 3, 2023

DynamicProxy currently does not support intercepting methods that have any by-ref-like (ref struct) parameter or return types (such as Span<T> or ReadOnlySpan<T>), because by-ref-like types cannot be converted to or from object. DynamicProxy however attempts such conversions when it transfers argument and return values into or out of IInvocation instances, thus causing InvalidProgramExceptions and, to a lesser degree, NullReferenceExceptions.

This PR targets the code locations (hopefully all of them) where such conversions between object and by-ref-like types occur, and suppresses those conversions in favor of writing certain default values:

  • null where assignments are made to IInvocation.Arguments or IInvocation.ReturnValue
  • the default value of the by-ref-like type where assignments are made to out arguments or when values are return-ed to callers.

This work should be merged before #664, because the code locations that it touches are the same ones where #664 would introduce (optional) user-defined conversions instead of always writing fixed default values.

This is currently still a draft because two things is still missing:

#651 will persist even after this, likely because by-ref-like argument values are still lost (reset) when proceeding to targets.

@stakx stakx self-assigned this Sep 3, 2023
@stakx stakx marked this pull request as draft September 3, 2023 21:51
@stakx stakx mentioned this pull request Sep 3, 2023
@stakx stakx force-pushed the bug/by-ref-like-parameters branch from 9f72f39 to 797f1da Compare December 9, 2025 23:52
@stakx stakx added this to the v6.0.0 milestone Dec 10, 2025
@stakx stakx force-pushed the bug/by-ref-like-parameters branch from 797f1da to bf58874 Compare December 10, 2025 12:07
@stakx stakx marked this pull request as ready for review December 10, 2025 12:07
@stakx stakx changed the title Draft: Prevent disallowed conversions between object and by-ref-like parameter and return types Prevent disallowed conversions between object and by-ref-like parameter and return types Dec 10, 2025
@stakx
Copy link
Member Author

stakx commented Dec 10, 2025

I think this is good to go. The AppVeyor test run fails only because of #704, and not because of any of the code changes made here. That can be fixed separately.

@stakx stakx force-pushed the bug/by-ref-like-parameters branch from bf58874 to 3ebf070 Compare December 10, 2025 13:23
 * Most tests fail with a `InvalidProgramException`: "Cannot create
   boxed ByRef-like values.".

 * One test fails with a `InvalidOperationException`: "Interceptors
   failed to set a return value [...]."
 * Wherever we are currently converting a by-ref-like argument or return
   value to `object`, we substitute `null` (because boxing is disallowed
   for by-ref-like types).

 * Wherever we convert from `object`, we substitute the default value
   for the by-ref-like type (because unboxing likewise doesn't work).

Such conversions happen in 4 places:

 1. at the beginning of the interception pipeline, where the original
    typed method call arguments are boxed into an `IInvocation`.

 2. when proceeding to a target, where the arguments are unboxed from
    the same `IInvocation` to typed method call arguments.

 3. when returning from a target, its outputs (by-ref parameters and
    the return value) must be boxed back into the `IInvocation`.

 4. at the end of the interception pipeline, its outputs (again, by-ref
    parameters and the return value) must be unboxed from `IInvocation`.
... which might be a bug in the runtime. We need a workaround for that.

See also:
dotnet/runtime#91532
@stakx stakx force-pushed the bug/by-ref-like-parameters branch from 3ebf070 to 1398959 Compare December 10, 2025 13:55
@stakx stakx merged commit 93e20a0 into castleproject:master Dec 10, 2025
4 checks passed
@stakx stakx deleted the bug/by-ref-like-parameters branch December 10, 2025 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant