Espressione .Compile in ambiente Medium Trust
-
02-10-2019 - |
Domanda
Quando si tenta di compilare un'espressione in una web app attendibilità media mi sto un MethodAccessException. Qualcuno sa di un altro modo per compilare un'espressione sotto trust media o una soluzione per evitare questa eccezione?
Il codice che genera l'eccezione:
Expression<Func<object>> efn =
Expression.Lambda<Func<object>>(Expression.Convert((plan,typeof(object)));
Func<object> fn = efn.Compile(); // Exception thrown here
Il piano variabile è un'espressione che rappresenta il seguente piano di esecuzione:
{
Convert(Query(MyProjectNamespace.MyDatabaseTableObject).Provider).Execute
(
new QueryCommand(
"SELECT [t0].[LinkId], [t0].[Url] FROM [dbo].[MyDatabaseTable] AS t0",
value(System.String[]),
r0 => new MyDatabaseTableObject()
{
Id = IIF(r0.IsDBNull(0), 0,
Convert(ChangeType(r0.GetValue(0), System.Int32))),
Url = IIF(r0.IsDBNull(1), null,
Convert(ChangeType(r0.GetValue(1), System.String)))
},
value(System.Collections.Generic.List[System.String])),
new [] {}
)
}
La traccia completa dello stack:
at System.Reflection.MethodBase.PerformSecurityCheck(Object obj, RuntimeMethodHandle method, IntPtr parent, UInt32 invocationFlags)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Linq.Expressions.ExpressionCompiler.AddGlobal(Type type, Object value)
at System.Linq.Expressions.ExpressionCompiler.GenerateConstant(ILGenerator gen, Type type, Object value, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConstant(ILGenerator gen, ConstantExpression c, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodInfo mi, ReadOnlyCollection`1 args, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodCallExpression mc, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConvert(ILGenerator gen, UnaryExpression u)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConditional(ILGenerator gen, ConditionalExpression b)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberAssignment(ILGenerator gen, MemberAssignment binding, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateBinding(ILGenerator gen, MemberBinding binding, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberInit(ILGenerator gen, ReadOnlyCollection`1 bindings, Boolean keepOnStack, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMemberInit(ILGenerator gen, MemberInitExpression init)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateLambda(LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.GenerateCreateDelegate(ILGenerator gen, LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateNew(ILGenerator gen, NewExpression nex, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateArgs(ILGenerator gen, ParameterInfo[] pis, ReadOnlyCollection`1 args)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodInfo mi, ReadOnlyCollection`1 args, Type objectType)
at System.Linq.Expressions.ExpressionCompiler.GenerateMethodCall(ILGenerator gen, MethodCallExpression mc, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateConvert(ILGenerator gen, UnaryExpression u)
at System.Linq.Expressions.ExpressionCompiler.Generate(ILGenerator gen, Expression node, StackType ask)
at System.Linq.Expressions.ExpressionCompiler.GenerateLambda(LambdaExpression lambda)
at System.Linq.Expressions.ExpressionCompiler.CompileDynamicLambda(LambdaExpression lambda)
at System.Linq.Expressions.Expression`1.Compile()
at SubSonic.Linq.Structure.DbQueryProvider.Execute(Expression expression)
at SubSonic.Linq.Structure.QueryProvider.System.Linq.IQueryProvider.Execute(Expression expression)
at SubSonic.Linq.Structure.Query`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at WebApplication1._Default.Page_Load(Object sender, EventArgs e)
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Soluzione
Il problema alla base è che il tipo sia passato al System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
non è o pubblico, o ha un costruttore che non è pubblico.
Ora - data la semplicità del tuo esempio di codice rispetto alla profondità della stacktrace credo le bugie problema non in plan
, ma in un'espressione all'interno plan
(dal momento che dici nel tuo commento alla risposta di Marc che è anche un'espressione) che i riferimenti del tipo che viene poi limitata.
L'espressione che è la fonte dell'errore ecco un ConstantExpression
che deve essere del tipo ristretto.
L'unica cosa confusione su questo, tuttavia, è che il tipo di argomento che AddGlobal
passa al Activator.CreateInstance
è StrongBox<T>
, che è pubblica e ha un costruttore pubblico -. Che implicherebbe che questo errore dovrebbe essere impossibile
Forse, però, c'è qualcosa di nascosto associato a StrongBox<T>
che non possiamo vedere attraverso riflettore.
Quindi, vorrei essere a guardare l'intero albero di espressione rappresentata da plan
ed esaminando tutti i tipi di riferimento in ConstantExpression
s per assicurare che sono tutti accessibili. Se dopo aver fatto che tutti i tipi sono indicati per essere accessibili, questo errore si verifica ancora, allora potrebbe essere un bug nel quadro.
Tuttavia - avrei pensato che un tale errore sarebbe stato trovato già da qualcosa di semplice come un ConstantExpression
Modifica (Edit Sostituzione precedente) CON LA RISPOSTA
ho capito, ed è un problema molto sottile. È possibile riprodurre con questo po 'di codice in una pagina aspx che è configurato per l'esecuzione in media fiducia:
Type t = typeof([any type you fancy]);
Expression expr = Expression.Constant(t);
var lambda = Expression.Lambda<Func<Type>>(expr);
var del = lambda.Compile();
Response.Write(del().ToString());
Quindi, il codice che ci hai fornito, è l'espressione che rappresenta il secondo argomento di ChangeType
(mi ha portato un po 'per rendersi conto che questo è un metodo di Sonic Sub), che sembra essere un Type
(non può vedere il codice, ma credo che sia una supposizione ragionevole!).
E 'cotto nell'espressione come ConstantExpression
di un'istanza Type
. Non chiedo come ho ristretto il parametro - un sacco di pila che strisciano e di lavoro parabola;)
Come accennato nella prima metà della mia risposta, è difficile vedere come il codice che l'espressione Albero usi compilatore potrà mai creare un MethodAccessException, dal momento che è sempre l'accesso alla ctor pubblico del tipo StrongBox<T>
.
Tuttavia, sarebbe si arrabbiano se il tipo passato come il generico non è pubblico. "Ma aspetta," dici, "Type
è pubblico!".
Questo potrebbe essere, ma l'istanza Type
restituita in fase di esecuzione da typeof()
o GetType()
non è - è un esempio di RuntimeType
- che è interno
Il che è anche il motivo per il frammento di codice di cui sopra sarà anche innescare lo stesso errore.
La correzione
Modificare il codice che produce l'argomento Type
per ChangeType(,)
da
Expression.Constant([type])
(che io quasi garantire che sia al momento) a
Expression.Constant([type], typeof(Type))
Questo funziona, perché si sta dicendo esplicitamente al compilatore di utilizzare il Type
pubblico per la costante, invece che il tipo di riflesso RuntimeType
.
È possibile verificare questa correzione applicandolo al mio codice di esempio nel blocco precedente e ri-esecuzione.