Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        public override object?Invoke(object?obj, BindingFlags invokeAttr, Binder?binder, object?[]?parameters, CultureInfo?culture)
        {
            if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
            {
                throw new NotSupportedException(SR.NotSupported_CallToVarArg);
            }

            //
            // We do not demand any permission here because the caller already has access
            // to the current DynamicMethod object, and it could just as easily emit another
            // Transparent DynamicMethod to call the current DynamicMethod.
            //

            _ = GetMethodDescriptor();
            // ignore obj since it's a static method

            // create a signature object
            Signature sig = new Signature(
                this.m_methodHandle !, m_parameterTypes, m_returnType, CallingConvention);


            // verify arguments
            int formalCount = sig.Arguments.Length;
            int actualCount = (parameters != null) ? parameters.Length : 0;

            if (formalCount != actualCount)
            {
                throw new TargetParameterCountException(SR.Arg_ParmCnt);
            }

            // if we are here we passed all the previous checks. Time to look at the arguments
            bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;

            StackAllocedArguments stackArgs = default;
            Span <object?>        arguments = default;

            if (actualCount != 0)
            {
                arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig.Arguments);
            }

            object?retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false, wrapExceptions);

            // copy out. This should be made only if ByRef are present.
            // n.b. cannot use Span<T>.CopyTo, as parameters.GetType() might not actually be typeof(object[])
            for (int index = 0; index < arguments.Length; index++)
            {
                parameters ![index] = arguments[index];
Exemplo n.º 3
0
        public override object?Invoke(
            object?obj, BindingFlags invokeAttr, Binder?binder, object?[]?parameters, CultureInfo?culture)
        {
            if ((InvocationFlags & InvocationFlags.NoInvoke) != 0)
            {
                ThrowNoInvokeException();
            }

            ValidateInvokeTarget(obj);

            if ((InvocationFlags & InvocationFlags.RunClassConstructor) != 0)
            {
                // Run the class constructor through the class constructor mechanism instead of the Invoke path.
                // This avoids allowing mutation of readonly static fields, and initializes the type correctly.
                InvokeClassConstructor();
                return(null);
            }

            // Correct number of arguments supplied
            int actualCount = (parameters is null) ? 0 : parameters.Length;

            if (ArgumentTypes.Length != actualCount)
            {
                throw new TargetParameterCountException(SR.Arg_ParmCnt);
            }

            StackAllocedArguments stackArgs = default;
            Span <object?>        arguments = default;

            if (actualCount != 0)
            {
                arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, ArgumentTypes);
            }

            object?retValue = InvokeWorker(obj, invokeAttr, arguments);

            // copy out. This should be made only if ByRef are present.
            // n.b. cannot use Span<T>.CopyTo, as parameters.GetType() might not actually be typeof(object[])
            for (int index = 0; index < arguments.Length; index++)
            {
                parameters ![index] = arguments[index];
Exemplo n.º 4
0
        public unsafe object?Invoke(
            object?thisPtr,
            IntPtr methodToCall,
            object?[]?parameters,
            BinderBundle?binderBundle,
            bool wrapInTargetInvocationException)
        {
            int argCount = parameters?.Length ?? 0;

            if (argCount != _argumentCount)
            {
                if (_argumentCount < 0)
                {
                    if (_argumentCount == ArgumentCount_NotSupported_ByRefLike)
                    {
                        throw new NotSupportedException(SR.NotSupported_ByRefLike);
                    }
                    throw new NotSupportedException();
                }

                throw new TargetParameterCountException(SR.Arg_ParmCnt);
            }

            object?returnObject = null;

            scoped ref byte thisArg = ref Unsafe.NullRef <byte>();

            if (!_isStatic)
            {
                // The caller is expected to validate this
                Debug.Assert(thisPtr != null);

                // See TODO comment in DynamicInvokeMethodThunk.NormalizeSignature
                // if (_isValueTypeInstanceMethod)
                // {
                //     // thisArg is a raw data byref for valuetype instance methods
                //     thisArg = ref thisPtr.GetRawData();
                // }
                // else
                {
                    thisArg = ref Unsafe.As <object?, byte>(ref thisPtr);
                }
            }

            scoped ref byte ret = ref Unsafe.As <object?, byte>(ref returnObject);

            if ((_returnTransform & Transform.AllocateReturnBox) != 0)
            {
                returnObject = RuntimeImports.RhNewObject(
                    (_returnTransform & Transform.Pointer) != 0 ?
                    EETypePtr.EETypePtrOf <IntPtr>() : _returnType);
                ret = ref returnObject.GetRawData();
            }

            if (argCount == 0)
            {
                try
                {
                    ret = ref RawCalliHelper.Call(InvokeThunk, (void *)methodToCall, ref thisArg, ref ret, null);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e) when(wrapInTargetInvocationException)
                {
                    throw new TargetInvocationException(e);
                }
            }
            else if (argCount > MaxStackAllocArgCount)
            {
                ret = ref InvokeWithManyArguments(methodToCall, ref thisArg, ref ret,
                                                  parameters, binderBundle, wrapInTargetInvocationException);
            }
            else
            {
                StackAllocedArguments argStorage   = default;
                StackAllocatedByRefs  byrefStorage = default;

                CheckArguments(ref argStorage._arg0 !, (ByReference *)&byrefStorage, parameters, binderBundle);

                try
                {
                    ret = ref RawCalliHelper.Call(InvokeThunk, (void *)methodToCall, ref thisArg, ref ret, &byrefStorage);
                    DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
                }
                catch (Exception e) when(wrapInTargetInvocationException)
                {
                    throw new TargetInvocationException(e);
                }
                finally
                {
                    if (_needsCopyBack)
                    {
                        CopyBack(ref argStorage._arg0 !, parameters);
                    }
                }
            }

            return(((_returnTransform & (Transform.Nullable | Transform.Pointer | Transform.ByRef)) != 0) ?
                   ReturnTransform(ref ret, wrapInTargetInvocationException) : returnObject);
        }