public override void SetValue(object obj, object val, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
 {
     if (!IsStatic)
     {
         if (obj == null)
         {
             throw new TargetException("Non-static field requires a target");
         }
         if (!DeclaringType.IsAssignableFrom(obj.GetType()))
         {
             throw new ArgumentException(string.Format(
                                             "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
                                             Name, DeclaringType, obj.GetType()),
                                         "obj");
         }
     }
     if (IsLiteral)
     {
         throw new FieldAccessException("Cannot set a constant field");
     }
     if (binder == null)
     {
         binder = Type.DefaultBinder;
     }
     CheckGeneric();
     if (val != null)
     {
         RuntimeType fieldType = (RuntimeType)FieldType;
         val = fieldType.CheckValue(val, binder, culture, invokeAttr);
     }
     SetValueInternal(this, obj, val);
 }
Ejemplo n.º 2
0
        public override void SetValue(object?obj, object?value, BindingFlags invokeAttr, Binder?binder, CultureInfo?culture)
        {
            INVOCATION_FLAGS invocationFlags = InvocationFlags;
            RuntimeType?     declaringType   = DeclaringType as RuntimeType;

            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
            {
                if (declaringType != null && declaringType.ContainsGenericParameters)
                {
                    throw new InvalidOperationException(SR.Arg_UnboundGenField);
                }

                throw new FieldAccessException();
            }

            CheckConsistency(obj);

            RuntimeType fieldType = (RuntimeType)FieldType;

            value = fieldType.CheckValue(value, binder, culture, invokeAttr);

            bool domainInitialized = false;

            if (declaringType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
            }
            else
            {
                domainInitialized = declaringType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
                declaringType.DomainInitialized = domainInitialized;
            }
        }
Ejemplo n.º 3
0
        internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
        {
            INVOCATION_FLAGS invocationFlags = InvocationFlags;
            RuntimeType declaringType = DeclaringType as RuntimeType;

            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
            {
                if (declaringType != null && declaringType.ContainsGenericParameters)
                    throw new InvalidOperationException(SR.Arg_UnboundGenField);

                if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
                    throw new InvalidOperationException(SR.Arg_ReflectionOnlyField);

                throw new FieldAccessException();
            }

            CheckConsistency(obj);

            RuntimeType fieldType = (RuntimeType)FieldType;
            value = fieldType.CheckValue(value, binder, culture, invokeAttr);

            bool domainInitialized = false;
            if (declaringType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
            }
            else
            {
                domainInitialized = declaringType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
                declaringType.DomainInitialized = domainInitialized;
            }
        }
Ejemplo n.º 4
0
        internal Object[] CheckArguments(Object[] parameters, Binder binder,
                                         BindingFlags invokeAttr, CultureInfo culture, Signature sig)
        {
            // copy the arguments in a different array so we detach from any user changes
            Object[] copyOfParameters = new Object[parameters.Length];

            ParameterInfo[] p = null;
            for (int i = 0; i < parameters.Length; i++)
            {
                Object      arg   = parameters[i];
                RuntimeType argRT = sig.Arguments[i];

                if (arg == Type.Missing)
                {
                    if (p == null)
                    {
                        p = GetParametersNoCopy();
                    }
                    if (p[i].DefaultValue == System.DBNull.Value)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"), "parameters");
                    }
                    arg = p[i].DefaultValue;
                }
                copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr);
            }

            return(copyOfParameters);
        }
        internal object[] CheckArguments(object[] parameters, Binder?binder,
                                         BindingFlags invokeAttr, CultureInfo?culture, Signature sig)
        {
            // copy the arguments in a different array so we detach from any user changes
            object[] copyOfParameters = new object[parameters.Length];

            ParameterInfo[]? p = null;
            for (int i = 0; i < parameters.Length; i++)
            {
                object      arg   = parameters[i];
                RuntimeType argRT = sig.Arguments[i];

                if (arg == Type.Missing)
                {
                    p ??= GetParametersNoCopy();
                    if (p[i].DefaultValue == System.DBNull.Value)
                    {
                        throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
                    }
                    arg = p[i].DefaultValue !;
                }
                copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr) !;
            }

            return(copyOfParameters);
        }
        internal object[] CheckArguments(object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
        {
            int num = (parameters != null) ? parameters.Length : 0;

            object[]        objArray         = new object[num];
            ParameterInfo[] parametersNoCopy = null;
            for (int i = 0; i < num; i++)
            {
                object      defaultValue = parameters[i];
                RuntimeType type         = sig.Arguments[i];
                if (defaultValue == Type.Missing)
                {
                    if (parametersNoCopy == null)
                    {
                        parametersNoCopy = this.GetParametersNoCopy();
                    }
                    if (parametersNoCopy[i].DefaultValue == DBNull.Value)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"), "parameters");
                    }
                    defaultValue = parametersNoCopy[i].DefaultValue;
                }
                objArray[i] = type.CheckValue(defaultValue, binder, culture, invokeAttr);
            }
            return(objArray);
        }
Ejemplo n.º 7
0
        internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
        {
            INVOCATION_FLAGS invocationFlags = InvocationFlags;
            RuntimeType      declaringType   = DeclaringType as RuntimeType;

            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
            {
                if (declaringType != null && declaringType.ContainsGenericParameters)
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
                }

                if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
                }

                throw new FieldAccessException();
            }

            CheckConsistency(obj);

            RuntimeType fieldType = (RuntimeType)FieldType;

            value = fieldType.CheckValue(value, binder, culture, invokeAttr);

            #region Security Check
#if FEATURE_APPX
            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
            {
                RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
                if (caller != null && !caller.IsSafeForReflection())
                {
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
                }
            }
#endif

            if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
            {
                PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)m_invocationFlags);
            }
            #endregion

            bool domainInitialized = false;
            if (declaringType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
            }
            else
            {
                domainInitialized = declaringType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
                declaringType.DomainInitialized = domainInitialized;
            }
        }
Ejemplo n.º 8
0
        private protected Span <object?> CheckArguments(
            ref StackAllocedArguments stackArgs,
            object?[]?parameters,
            Binder?binder,
            BindingFlags invokeAttr,
            CultureInfo?culture,
            Signature sig
            )
        {
            Debug.Assert(
                Unsafe.SizeOf <StackAllocedArguments>()
                == StackAllocedArguments.MaxStackAllocArgCount * Unsafe.SizeOf <object>(),
                "MaxStackAllocArgCount not properly defined."
                );

            Span <object?> copyOfParameters = default;

            if (parameters is not null)
            {
                // We need to perform type safety validation against the incoming arguments, but we also need
                // to be resilient against the possibility that some other thread (or even the binder itself!)
                // may mutate the array after we've validated the arguments but before we've properly invoked
                // the method. The solution is to copy the arguments to a different, not-user-visible buffer
                // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are
                // considered user-visible to threads which may still be holding on to returned instances.

                copyOfParameters =
                    (parameters.Length <= StackAllocedArguments.MaxStackAllocArgCount)
                        ? MemoryMarshal.CreateSpan(ref stackArgs._arg0, parameters.Length)
                        : new Span <object?>(new object?[parameters.Length]);

                ParameterInfo[]? p = null;
                for (int i = 0; i < parameters.Length; i++)
                {
                    object?     arg   = parameters[i];
                    RuntimeType argRT = sig.Arguments[i];

                    if (arg == Type.Missing)
                    {
                        p ??= GetParametersNoCopy();
                        if (p[i].DefaultValue == System.DBNull.Value)
                        {
                            throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
                        }
                        arg = p[i].DefaultValue !;
                    }
                    copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr);
                }
            }

            return(copyOfParameters);
        }
        internal void InternalSetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
        {
            INVOCATION_FLAGS invocationFlags = this.InvocationFlags;
            RuntimeType      runtimeType     = this.DeclaringType as RuntimeType;

            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
            {
                if (runtimeType != null && runtimeType.ContainsGenericParameters)
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
                }
                if ((runtimeType == null && this.Module.Assembly.ReflectionOnly) || runtimeType is ReflectionOnlyType)
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
                }
                throw new FieldAccessException();
            }
            else
            {
                this.CheckConsistency(obj);
                RuntimeType runtimeType2 = (RuntimeType)this.FieldType;
                value = runtimeType2.CheckValue(value, binder, culture, invokeAttr);
                if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
                {
                    RuntimeAssembly executingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
                    if (executingAssembly != null && !executingAssembly.IsSafeForReflection())
                    {
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", new object[]
                        {
                            this.FullName
                        }));
                    }
                }
                if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY | INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR)) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
                {
                    RtFieldInfo.PerformVisibilityCheckOnField(this.m_fieldHandle, obj, this.m_declaringType, this.m_fieldAttributes, (uint)this.m_invocationFlags);
                }
                bool domainInitialized = false;
                if (runtimeType == null)
                {
                    RuntimeFieldHandle.SetValue(this, obj, value, runtimeType2, this.m_fieldAttributes, null, ref domainInitialized);
                    return;
                }
                domainInitialized = runtimeType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, runtimeType2, this.m_fieldAttributes, runtimeType, ref domainInitialized);
                runtimeType.DomainInitialized = domainInitialized;
                return;
            }
        }
        internal void UnsafeSetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
        {
            RuntimeType runtimeType  = this.DeclaringType as RuntimeType;
            RuntimeType runtimeType2 = (RuntimeType)this.FieldType;

            value = runtimeType2.CheckValue(value, binder, culture, invokeAttr);
            bool domainInitialized = false;

            if (runtimeType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, runtimeType2, this.m_fieldAttributes, null, ref domainInitialized);
                return;
            }
            domainInitialized = runtimeType.DomainInitialized;
            RuntimeFieldHandle.SetValue(this, obj, value, runtimeType2, this.m_fieldAttributes, runtimeType, ref domainInitialized);
            runtimeType.DomainInitialized = domainInitialized;
        }
Ejemplo n.º 11
0
        internal void UnsafeSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
        {
            RuntimeType declaringType = DeclaringType as RuntimeType;
            RuntimeType fieldType = (RuntimeType)FieldType;
            value = fieldType.CheckValue(value, binder, culture, invokeAttr);

            bool domainInitialized = false;
            if (declaringType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
            }
            else
            {
                domainInitialized = declaringType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
                declaringType.DomainInitialized = domainInitialized;
            }
        }
Ejemplo n.º 12
0
        internal void InternalSetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, bool doVisibilityCheck, bool doCheckConsistency)
        {
            INVOCATION_FLAGS invocationFlags = this.InvocationFlags;
            RuntimeType      declaringType   = this.DeclaringType as RuntimeType;

            if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN)
            {
                if ((declaringType != null) && declaringType.ContainsGenericParameters)
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
                }
                if (((declaringType != null) || !this.Module.Assembly.ReflectionOnly) && !(declaringType is ReflectionOnlyType))
                {
                    throw new FieldAccessException();
                }
                throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
            }
            if (doCheckConsistency)
            {
                this.CheckConsistency(obj);
            }
            RuntimeType fieldType = (RuntimeType)this.FieldType;

            value = fieldType.CheckValue(value, binder, culture, invokeAttr);
            if (doVisibilityCheck && ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN))
            {
                PerformVisibilityCheckOnField(this.m_fieldHandle, obj, base.m_declaringType, this.m_fieldAttributes, (uint)this.m_invocationFlags);
            }
            bool domainInitialized = false;

            if (declaringType == null)
            {
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, this.m_fieldAttributes, null, ref domainInitialized);
            }
            else
            {
                domainInitialized = declaringType.DomainInitialized;
                RuntimeFieldHandle.SetValue(this, obj, value, fieldType, this.m_fieldAttributes, declaringType, ref domainInitialized);
                declaringType.DomainInitialized = domainInitialized;
            }
        }
Ejemplo n.º 13
0
        public override void SetValue(object?obj, object?val, BindingFlags invokeAttr, Binder?binder, CultureInfo?culture)
        {
            if (!IsStatic)
            {
                if (obj == null)
                {
                    throw new TargetException("Non-static field requires a target");
                }
                if (!DeclaringType !.IsAssignableFrom(obj.GetType()))
                {
                    throw new ArgumentException(string.Format(
                                                    "Field {0} defined on type {1} is not a field on the target object which is of type {2}.",
                                                    Name, DeclaringType, obj.GetType()),
                                                nameof(obj));
                }
            }
            if (IsLiteral)
            {
                throw new FieldAccessException("Cannot set a constant field");
            }
            if (binder == null)
            {
                binder = Type.DefaultBinder;
            }
            CheckGeneric();
            if (val != null)
            {
                RuntimeType             fieldType = (RuntimeType)FieldType;
                ParameterCopyBackAction _         = default;

                if (!ReferenceEquals(val.GetType(), fieldType))
                {
                    fieldType.CheckValue(ref val, ref _, binder, culture, invokeAttr);
                }
            }

            Invoker.SetValue(obj, val);
        }
Ejemplo n.º 14
0
 internal object[] CheckArguments(object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
 {
     object[]        objArray           = new object[parameters.Length];
     ParameterInfo[] parameterInfoArray = (ParameterInfo[])null;
     for (int index = 0; index < parameters.Length; ++index)
     {
         object      obj         = parameters[index];
         RuntimeType runtimeType = sig.Arguments[index];
         if (obj == Type.Missing)
         {
             if (parameterInfoArray == null)
             {
                 parameterInfoArray = this.GetParametersNoCopy();
             }
             if (parameterInfoArray[index].DefaultValue == DBNull.Value)
             {
                 throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"), "parameters");
             }
             obj = parameterInfoArray[index].DefaultValue;
         }
         objArray[index] = runtimeType.CheckValue(obj, binder, culture, invokeAttr);
     }
     return(objArray);
 }
Ejemplo n.º 15
0
        private protected unsafe void CheckArguments(
            Span <object?> copyOfParameters,
            IntPtr *byrefParameters,
            Span <ParameterCopyBackAction> shouldCopyBack,
            ReadOnlySpan <object?> parameters,
            RuntimeType[] sigTypes,
            Binder?binder,
            CultureInfo?culture,
            BindingFlags invokeAttr
            )
        {
            Debug.Assert(parameters.Length > 0);

            ParameterInfo[]? paramInfos = null;
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterCopyBackAction copyBackArg = default;
                bool        isValueType             = false;
                object?     arg     = parameters[i];
                RuntimeType sigType = sigTypes[i];

                // Convert a Type.Missing to the default value.
                if (ReferenceEquals(arg, Type.Missing))
                {
                    paramInfos ??= GetParametersNoCopy();
                    ParameterInfo paramInfo = paramInfos[i];

                    if (paramInfo.DefaultValue == DBNull.Value)
                    {
                        throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
                    }

                    arg = paramInfo.DefaultValue;

                    if (sigType.IsNullableOfT)
                    {
                        copyBackArg = ParameterCopyBackAction.CopyNullable;

                        if (arg is not null)
                        {
                            // For nullable Enum types, the ParameterInfo.DefaultValue returns a raw value which
                            // needs to be parsed to the Enum type, for more info: https://github.com/dotnet/runtime/issues/12924
                            Type argumentType = sigType.GetGenericArguments()[0];
                            if (argumentType.IsEnum)
                            {
                                arg = Enum.ToObject(argumentType, arg);
                            }
                        }
                    }
                    else
                    {
                        copyBackArg = ParameterCopyBackAction.Copy;
                    }
                }

                if (arg is null)
                {
                    // Fast path for null reference types.
                    isValueType = RuntimeTypeHandle.IsValueType(sigType);
                    if (isValueType || RuntimeTypeHandle.IsByRef(sigType))
                    {
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                }
                else
                {
                    RuntimeType argType = (RuntimeType)arg.GetType();

                    if (ReferenceEquals(argType, sigType))
                    {
                        // Fast path when the value's type matches the signature type.
                        isValueType = RuntimeTypeHandle.IsValueType(argType);
                    }
                    else if (sigType.TryByRefFastPath(ref arg, ref isValueType))
                    {
                        // Fast path when the value's type matches the signature type of a byref parameter.
                        copyBackArg = ParameterCopyBackAction.Copy;
                    }
                    else
                    {
                        // Slow path that supports type conversions.
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                }

                // We need to perform type safety validation against the incoming arguments, but we also need
                // to be resilient against the possibility that some other thread (or even the binder itself!)
                // may mutate the array after we've validated the arguments but before we've properly invoked
                // the method. The solution is to copy the arguments to a different, not-user-visible buffer
                // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are
                // considered user-visible to threads which may still be holding on to returned instances.
                // This separate array is also used to hold default values when 'null' is specified for value
                // types, and also used to hold the results from conversions such as from Int16 to Int32. For
                // compat, these default values and conversions are not be applied to the incoming arguments.
                shouldCopyBack[i]   = copyBackArg;
                copyOfParameters[i] = arg;

                if (isValueType)
                {
#if !MONO // Temporary until Mono is updated.
                    Debug.Assert(arg != null);
                    Debug.Assert(
                        arg.GetType() == sigType ||
                        (sigType.IsPointer && (arg.GetType() == typeof(IntPtr) || arg.GetType() == typeof(UIntPtr))) ||
                        (sigType.IsByRef && arg.GetType() == RuntimeTypeHandle.GetElementType(sigType)) ||
                        ((sigType.IsEnum || arg.GetType().IsEnum) && RuntimeType.GetUnderlyingType((RuntimeType)arg.GetType()) == RuntimeType.GetUnderlyingType(sigType)));
#endif
                    ByReference valueTypeRef = ByReference.Create(ref copyOfParameters[i] !.GetRawData());
                    *(ByReference *)(byrefParameters + i) = valueTypeRef;
                }
                else
                {
                    ByReference objRef = ByReference.Create(ref copyOfParameters[i]);
                    *(ByReference *)(byrefParameters + i) = objRef;
                }
            }
        }
Ejemplo n.º 16
0
        private protected unsafe void CheckArguments(
            Span <object?> copyOfParameters,
            IntPtr *byrefParameters,
            Span <bool> shouldCopyBack,
            ReadOnlySpan <object?> parameters,
            RuntimeType[] sigTypes,
            Binder?binder,
            CultureInfo?culture,
            BindingFlags invokeAttr
            )
        {
            Debug.Assert(!parameters.IsEmpty);

            ParameterInfo[]? paramInfos = null;
            for (int i = 0; i < parameters.Length; i++)
            {
                bool        copyBackArg = false;
                bool        isValueType;
                object?     arg     = parameters[i];
                RuntimeType sigType = sigTypes[i];

                if (arg is null)
                {
                    // Fast path that avoids calling CheckValue() for reference types.
                    isValueType = RuntimeTypeHandle.IsValueType(sigType);
                    if (isValueType || RuntimeTypeHandle.IsByRef(sigType))
                    {
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                }
                else if (ReferenceEquals(arg.GetType(), sigType))
                {
                    // Fast path that avoids calling CheckValue() when argument value matches the signature type.
                    isValueType = RuntimeTypeHandle.IsValueType(sigType);
                }
                else
                {
                    paramInfos ??= GetParametersNoCopy();
                    ParameterInfo paramInfo = paramInfos[i];
                    if (!ReferenceEquals(arg, Type.Missing))
                    {
                        isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                    }
                    else
                    {
                        if (paramInfo.DefaultValue == DBNull.Value)
                        {
                            throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
                        }

                        arg = paramInfo.DefaultValue;
                        if (ReferenceEquals(arg?.GetType(), sigType))
                        {
                            isValueType = RuntimeTypeHandle.IsValueType(sigType);
                        }
                        else
                        {
                            isValueType = sigType.CheckValue(ref arg, ref copyBackArg, binder, culture, invokeAttr);
                        }
                    }
                }

                // We need to perform type safety validation against the incoming arguments, but we also need
                // to be resilient against the possibility that some other thread (or even the binder itself!)
                // may mutate the array after we've validated the arguments but before we've properly invoked
                // the method. The solution is to copy the arguments to a different, not-user-visible buffer
                // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are
                // considered user-visible to threads which may still be holding on to returned instances.
                // This separate array is also used to hold default values when 'null' is specified for value
                // types, and also used to hold the results from conversions such as from Int16 to Int32; these
                // default values and conversions should not be applied to the incoming arguments.
                shouldCopyBack[i]   = copyBackArg;
                copyOfParameters[i] = arg;

                if (isValueType)
                {
#if DEBUG
                    // Once Mono has managed conversion logic, VerifyValueType() can be lifted here as Asserts.
                    sigType.VerifyValueType(arg);
#endif
                    ByReference <byte> valueTypeRef = new(ref copyOfParameters[i] !.GetRawData());
                    *(ByReference <byte> *)(byrefParameters + i) = valueTypeRef;
                }
                else
                {
                    ByReference <object?> objRef = new(ref copyOfParameters[i]);
                    *(ByReference <object?> *)(byrefParameters + i) = objRef;
                }
            }
        }