public static ExecutionResultWrapper Execute(Stream assemblyStream, RuntimeGuardToken guardToken) { try { Console.SetOut(Output.Writer); var assembly = Assembly.Load(ReadAllBytes(assemblyStream)); var main = assembly.EntryPoint; using (guardToken.Scope(NewRuntimeGuardSettings())) { var args = main.GetParameters().Length > 0 ? new object[] { new string[0] } : null; var result = main.Invoke(null, args); if (main.ReturnType != typeof(void)) { result.Inspect("Return"); } return(new ExecutionResultWrapper(new ExecutionResult(Output.Stream, Flow.Steps), null)); } } catch (Exception ex) { if (ex is TargetInvocationException invocationEx) { ex = invocationEx.InnerException; } Flow.ReportException(ex); ex.Inspect("Exception"); return(new ExecutionResultWrapper(new ExecutionResult(Output.Stream, Flow.Steps), ex)); } }
public unsafe ExecutionResult Execute(Assembly assembly, RuntimeGuardToken guardToken, IWorkSession session) { try { Output.Reset(); Flow.Reset(); Console.SetOut(Output.Writer); var main = assembly.EntryPoint; if (main == null) { throw new ArgumentException("Entry point not found in " + assembly, nameof(assembly)); } using (guardToken.Scope(NewRuntimeGuardSettings())) { var args = main.GetParameters().Length > 0 ? new object[] { new string[0] } : null; PerformanceLog.Checkpoint("Executor.Invoke.Start"); var result = main.Invoke(null, args); PerformanceLog.Checkpoint("Executor.Invoke.End"); if (main.ReturnType != typeof(void)) { result.Inspect("Return"); } return(new ExecutionResult(Output.Stream, Flow.Steps)); } } catch (Exception ex) { PerformanceLog.Checkpoint("Executor.Invoke.Exception"); if (ex is TargetInvocationException invocationEx) { ex = invocationEx.InnerException ?? ex; } if (ex is RegexMatchTimeoutException) { ex = new TimeGuardException("Time limit reached while evaluating a Regex.\r\nNote that timeout was added by SharpLab — in real code this would not throw, but might run for a very long time.", ex); } if (ex is StackGuardException sgex) { throw new Exception($"{sgex.Message} {sgex.StackBaseline} {sgex.StackOffset} {sgex.StackLimit} {sgex.StackSize}"); } Flow.ReportException(ex); Output.Write(new SimpleInspection("Exception", ex.ToString())); if (ShouldMonitorException(ex)) { _monitor.Exception(ex !, session); } return(new ExecutionResult(Output.Stream, Flow.Steps)); } }
private ExecutionResult ExecuteInAppDomain(MemoryStream assemblyStream, RuntimeGuardToken guardToken, IWorkSession session) { var currentSetup = AppDomain.CurrentDomain.SetupInformation; using (var context = AppDomainContext.Create(new AppDomainSetup { ApplicationBase = currentSetup.ApplicationBase, PrivateBinPath = currentSetup.PrivateBinPath })) { context.LoadAssembly(LoadMethod.LoadFrom, Assembly.GetExecutingAssembly().GetAssemblyFile().FullName); var(result, exception) = RemoteFunc.Invoke(context.Domain, assemblyStream, guardToken, CurrentProcess.Id, Remote.Execute); if (ShouldMonitorException(exception)) { _monitor.Exception(exception, session); } return(result); } }
private static object?RemoteRun(MemoryStream assemblyStream, RuntimeGuardToken token) { using (token.Scope()) { var assembly = Assembly.Load(assemblyStream.ToArray()); var type = assembly.GetType("Program", true); var method = type.GetMethod("Run", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (method == null) { throw new NotSupportedException("Static method 'Run' not found on type 'Program'."); } var result = method.Invoke(null, null); if (result?.GetType().Assembly == assembly || (result is MemberInfo m && m.Module.Assembly == assembly)) { throw new Exception("Result returned by Program.Run must not belong to the user assembly."); } return(result); } }
public static ExecutionResultWithException Execute(byte[] assemblyBytes, RuntimeGuardToken guardToken, int processId, bool profilerActive) { var assembly = Assembly.Load(assemblyBytes); return(IsolatedExecutorCore.Execute(assembly, guardToken.Guid, processId, profilerActive)); }
protected override ExecutionResultWithException ExecuteWithIsolation(MemoryStream assemblyStream, RuntimeGuardToken guardToken, IWorkSession session) { var currentSetup = AppDomain.CurrentDomain.SetupInformation; using (var context = AppDomainContext.Create(new AppDomainSetup { ApplicationBase = currentSetup.ApplicationBase, PrivateBinPath = currentSetup.PrivateBinPath })) { context.LoadAssembly(LoadMethod.LoadFrom, Assembly.GetExecutingAssembly().GetAssemblyFile().FullName); return(RemoteFunc.Invoke(context.Domain, assemblyStream.ToArray(), guardToken, Current.ProcessId, ProfilerState.Active, Remote.Execute)); } }
protected override ExecutionResultWithException ExecuteWithIsolation(MemoryStream assemblyStream, RuntimeGuardToken guardToken, IWorkSession session) { using (var context = new CustomAssemblyLoadContext(shouldShareAssembly: _ => false)) { var assembly = context.LoadFromStream(assemblyStream); var serverAssembly = context.LoadFromAssemblyPath(Current.AssemblyPath); var coreType = serverAssembly.GetType(typeof(IsolatedExecutorCore).FullName); var execute = coreType.GetMethod(nameof(IsolatedExecutorCore.Execute)); var wrapperInContext = execute.Invoke(null, new object[] { assembly, guardToken.Guid, Current.ProcessId, ProfilerState.Active }); // Since wrapperInContext belongs to a different AssemblyLoadContext, it is not possible to convert // it to same type in the default context without some trick (e.g. serialization). using (var wrapperStream = _memoryStreamManager.GetStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(wrapperStream, wrapperInContext); wrapperStream.Seek(0, SeekOrigin.Begin); return((ExecutionResultWithException)formatter.Deserialize(wrapperStream)); } } }
public RuntimeGuardScope(RuntimeGuardToken token, RuntimeGuardSettings settings) { _guid = token.Guid; RuntimeGuardInstances.Start(_guid, settings); }
public static unsafe ExecutionResultWrapper Execute(Stream assemblyStream, RuntimeGuardToken guardToken, int processId) { try { Console.SetOut(Output.Writer); InspectionSettings.CurrentProcessId = processId; var assembly = Assembly.Load(ReadAllBytes(assemblyStream)); var main = assembly.EntryPoint; using (guardToken.Scope(NewRuntimeGuardSettings())) { var args = main.GetParameters().Length > 0 ? new object[] { new string[0] } : null; byte *stackStart = stackalloc byte[1]; InspectionSettings.StackStart = (ulong)stackStart; var result = main.Invoke(null, args); if (main.ReturnType != typeof(void)) { result.Inspect("Return"); } return(new ExecutionResultWrapper(new ExecutionResult(Output.Stream, Flow.Steps), null)); } } catch (Exception ex) { if (ex is TargetInvocationException invocationEx) { ex = invocationEx.InnerException; } if (ex is RegexMatchTimeoutException) { ex = new TimeGuardException("Time limit reached while evaluating a Regex.\r\nNote that timeout was added by SharpLab — in real code this would not throw, but might run for a very long time.", ex); } Flow.ReportException(ex); ex.Inspect("Exception"); return(new ExecutionResultWrapper(new ExecutionResult(Output.Stream, Flow.Steps), ex)); } }
protected abstract ExecutionResultWithException ExecuteWithIsolation(MemoryStream assemblyStream, RuntimeGuardToken guardToken, IWorkSession session);