@@ -500,6 +500,43 @@ public void By_ref_like_out_arguments_cannot_be_set_by_target()
500500
501501 #endregion
502502
503+ #region Memory safety
504+
505+ // Byref-like arguments live exclusively on the evaluation stack.
506+ // We need to make sure that references to them (such as those in `IInvocation.Arguments`)
507+ // do not have a longer lifetime than the arguments themselves.
508+
509+ [ Test ]
510+ public unsafe void Cannot_use_ByRefLikeArgument_GetPointer_after_invocation ( )
511+ {
512+ var interceptor = new ObservingInterceptor ( ) ;
513+ var proxy = generator . CreateClassProxy < HasMethodWithSpanParameter > ( interceptor ) ;
514+ proxy . Method ( default ) ;
515+ var byRefLikeArg = ( ByRefLikeArgument ) interceptor . ObservedArg ! ;
516+ Assert . Throws < ObjectDisposedException > ( ( ) => _ = byRefLikeArg . GetPointer ( ) ) ;
517+ }
518+
519+ [ Test ]
520+ public void Cannot_use_ByRefLikeArgument_Get_after_invocation ( )
521+ {
522+ var interceptor = new ObservingInterceptor ( ) ;
523+ var proxy = generator . CreateClassProxy < HasMethodWithSpanParameter > ( interceptor ) ;
524+ proxy . Method ( default ) ;
525+ var byRefLikeArg = ( ReadOnlySpanArgument < char > ) interceptor . ObservedArg ! ;
526+ Assert . Throws < ObjectDisposedException > ( ( ) => _ = byRefLikeArg . Get ( ) ) ;
527+ }
528+
529+ [ Test ]
530+ public void ByRefLikeArguments_are_erased_from_invocation_Arguments_after_invocation ( )
531+ {
532+ var interceptor = new ObservingInterceptor ( ) ;
533+ var proxy = generator . CreateClassProxy < HasMethodWithSpanParameter > ( interceptor ) ;
534+ proxy . Method ( default ) ;
535+ Assert . IsNull ( interceptor . AllArguments ! [ 0 ] ) ;
536+ }
537+
538+ #endregion
539+
503540 public class HasMethodWithSpanParameter
504541 {
505542 public string ? RecordedArg ;
@@ -541,10 +578,12 @@ public virtual void Method(out ReadOnlySpan<char> arg)
541578
542579 public class ObservingInterceptor : IInterceptor
543580 {
581+ public object ? [ ] ? AllArguments ;
544582 public object ? ObservedArg ;
545583
546584 public void Intercept ( IInvocation invocation )
547585 {
586+ AllArguments = invocation . Arguments ;
548587 ObservedArg = invocation . Arguments [ 0 ] ;
549588 }
550589 }
0 commit comments