protected virtual bool CheckCodeBlock(RunOptsBase opts, ref RunResult runResult) { if (opts.CodeBlock == null) opts.CodeBlock = new ConsoleOrScriptCodeBlock { CodeBlock = string.Empty }; else if (((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock == null) ((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock = string.Empty; return CheckCodeSizeLimit(((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock, ref runResult); }
protected override bool CheckCodeBlock(RunOptsBase opts, ref RunResult runResult) { if (opts.CodeBlock == null) opts.CodeBlock = new MvcCodeBlock { Model = string.Empty, View = string.Empty, Controller = string.Empty }; var codeBlock = (MvcCodeBlock) opts.CodeBlock; return CheckCodeSizeLimit(codeBlock.Model, ref runResult) && CheckCodeSizeLimit(codeBlock.Controller, ref runResult); }
protected override void RunInteractive(RunOptsBase opts, RunResult result) { new PermissionSet(PermissionState.Unrestricted).Assert(); CommonScriptEngine scriptEngine = this.CreateSciptEngine(); Session session = scriptEngine.CreateSession(); var codeBlock = (ConsoleOrScriptCodeBlock) opts.CodeBlock; var referencedDlls = this.GetGacDlls(codeBlock.CodeBlock); foreach (var referenceDll in referencedDlls) session.AddReference(referenceDll); var libs = GetNonGacDlls(); foreach (var path in libs) { session.AddReference(path); } Submission<object> submission; try { // we compile code there submission = session.CompileSubmission<object>(codeBlock.CodeBlock); } catch (ThreadAbortException) { throw; } catch (Exception ex) { if (!string.IsNullOrEmpty(ex.Message) && ex.Message.Contains(ErrorWhenCompileConsoleProjectAsScript)) {/*Case 4067: DotNetFiddle throws exception on VbNet Script * https://entech.fogbugz.com/default.asp?4067#31607 * This issue occurs, when user is trying to compile VB.Net Console project as VB.Net Script project. * So, there is main entry point 'Module Sub Main' in snippet. * Then Roslyn throws following exception "(3) : error BC35000: Requested operation is not available because the runtime library function 'Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute..ctor' is not defined." * In same case for C#, Roslyn just ignores 'console' code. * So for VB.Net case we just return 'success' and empty string. */ result.IsSuccess = true; result.ConsoleOutput = ""; } else { ValidateCodeResult validateCodeResult = ValidateCode(codeBlock.CodeBlock); result.IsSuccess = false; result.FailureType = RunResultFailureType.CompilerErrors; result.CompilerErrors = validateCodeResult.Errors; } if (result.CompilerErrors == null) { result.CompilerErrors = new List<ValidationError> {ValidationError.CreateFromException(ex)}; } TryCleanRoslynCacheHack(); PermissionSet.RevertAssert(); return; } object execResult = null; try { this.OnStartingExecution(); PermissionSet.RevertAssert(); execResult = submission.Execute(); this.OnFinishedExecution(); } catch (ThreadAbortException) { throw; } catch (Exception ex) { result.IsSuccess = false; result.FailureType = RunResultFailureType.RunTimeException; result.RunTimeException = new ExceptionInfo(ex); } finally { result.ConsoleOutput = _consoleWriter.ToString().TrimEnd(); if (execResult != null) { result.ConsoleOutput += Environment.NewLine; result.ConsoleOutput += "[Return value]: " + execResult; } // don't need it as we modified Roslyn assemblies and made fix in them // TryCleanRoslynCacheHack(); } }
protected virtual void RunMvc(RunOptsBase opts, RunResult result) { throw new NotImplementedException(); }
protected abstract void RunInteractive(RunOptsBase opts, RunResult result);
private void RunConsole(RunOptsBase opts, RunResult result) { new PermissionSet(PermissionState.Unrestricted).Assert(); CompilerResults compilerResults; compilerResults = CompileConsole(opts, 4); if (!IsCompilationSucceed(compilerResults, result)) { PermissionSet.RevertAssert(); return; } MethodInfo mainMethodInfo; object ownerInstance; mainMethodInfo = GetMainMethodAndOwnerInstance(compilerResults.CompiledAssembly, out ownerInstance); if (mainMethodInfo == null || !mainMethodInfo.IsPublic || !mainMethodInfo.DeclaringType.IsPublic) { result.IsSuccess = false; result.FailureType = RunResultFailureType.FatalError; result.FatalErrorMessage = "Public Main() method is required in a public class"; return; } try { this.OnStartingExecution(); PermissionSet.RevertAssert(); //Add timer so doesn't execute for more then 5 secs var paramInfos = mainMethodInfo.GetParameters(); mainMethodInfo.Invoke(ownerInstance, paramInfos.Select(pi => (object)null).ToArray()); this.OnFinishedExecution(); } catch (ThreadAbortException) { throw; } catch (Exception ex) { result.IsSuccess = false; result.FailureType = RunResultFailureType.RunTimeException; result.RunTimeException = new ExceptionInfo(ex.InnerException ?? ex); } finally { result.ConsoleOutput = _consoleWriter.ToString().TrimEnd(); } }
protected bool IsCompilationSucceed(CompilerResults compilerResults, RunResult result) { if (compilerResults.Errors.HasErrors) { result.IsSuccess = false; result.FailureType = RunResultFailureType.CompilerErrors; result.CompilerErrors = GetValidationErrorsFromCompilerErrors(compilerResults.Errors); return false; } return true; }
public RunResult Run(RunOptsBase opts) { RunResult result = null; if (!CheckCodeBlock(opts, ref result)) return result; // we should copy it before running, becuase it can be changed during execution var sandboxFolder = _sandboxFolder; var codeHelper = SandboxHelper.ExecuteInFullTrust(() =>(CodeHelper)Activator.CreateInstance(_codeHelperType)); codeHelper.NuGetDllReferences = opts.NuGetDllReferences; codeHelper.StartingExecution += this.CodeHelper_StartingExecution; codeHelper.FinishedExecution += this.CodeHelper_FinishedExecution; codeHelper.RequestedConsoleInput += this.CodeHelper_RequestedConsoleInput; _executingThread = new Thread( () => { try { _runAt = DateTime.Now; result = this.ExecuteCodeBlock(opts, codeHelper); } finally { // in theory in can be null at this point if something bad happened.... if (result == null) { result = new RunResult() { FailureType = RunResultFailureType.FatalError, IsSuccess = false }; } result.Stats = SandboxHelper.ExecuteInFullTrust(() => GatherStatistics()); _compilationCompleted.Set(); } }); _executingThread.Start(); var monitoringTask = Task.Factory.StartNew(MonitorHealth, _tokenSource.Token); // wait for compilation. Just to be sure we have 15 seconds timeout _compilationCompleted.WaitOne(TimeSpan.FromSeconds(15)); // if something happened during compilation, then we fire _compilationCompleted on exit, and result will be filled, so we just need to return it if (result != null) { return result; } // it will use some time for compilation // it can hungs for some unmanaged call like Console.ReadKey(), so we wait with timeout // we might need to rewrite it to ManualEvent that will be fired when CodeHelper starts execution _executingThread.Join(WorkerConfiguration.Current.ExecutionLimitTimeoutMs * 2); _tokenSource.Cancel(); // we can't move it to new method, as it can be executed via reflection SandboxHelper.ExecuteInFullTrust( () => { try { if (Directory.Exists(sandboxFolder)) { foreach (var file in Directory.EnumerateFiles(sandboxFolder, "*", SearchOption.AllDirectories)) { File.Delete(file); } } } catch { if (result != null) result.SandboxUnloadReason = SandboxUnloadReason.ClearDirFailed; } }); return result; }
protected abstract void RunInteractive(RunOptsBase opts, RunResult result);
public RunResult Run(RunOptsBase opts) { var result = new RunResult(); result.IsSuccess = true; _consoleReader.InputLines = opts.ConsoleInputLines; if (!VerifyDeniedCodeBlock(opts, result)) { return result; } ResolveEventHandler handler = (o, e) => CurrentDomain_AssemblyResolve(opts, e); TextWriter defaultConsoleOut = Console.Out; TextReader defaultConsoleIn = Console.In; SandboxHelper.ExecuteInFullTrust( () => { Console.SetOut(_consoleWriter); Console.SetIn(_consoleReader); }); try { AppDomain.CurrentDomain.AssemblyResolve += handler; switch (ProjectType) { case ProjectType.Console: RunConsole(opts, result); break; case ProjectType.Script: RunInteractive(opts, result); break; case ProjectType.Mvc: RunMvc(opts, result); break; default: throw new NotImplementedException(); } } catch (ThreadAbortException ex) { var consoleInputRequest = ex.ExceptionState as ConsoleInputRequest; if (consoleInputRequest != null) { result.IsSuccess = true; result.IsConsoleInputRequested = true; } else { result.IsSuccess = false; var limit = ex.ExceptionState as LimitExceededException; if (limit != null) { result.FailureType = RunResultFailureType.FatalError; result.FatalErrorMessage = LimitExceededException.FormatMessage(limit.LimitType); } } SandboxHelper.ExecuteInFullTrust(Thread.ResetAbort); } finally { //Restore Console Out just in case SandboxHelper.ExecuteInFullTrust( () => { Console.SetOut(defaultConsoleOut); Console.SetIn(defaultConsoleIn); }); // unsubscribe AppDomain.CurrentDomain.AssemblyResolve -= handler; } return result; }
protected override bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result) { var codeBlock = ((NancyFxCodeBlock) opts.CodeBlock); var aggregateCode = codeBlock.Controller + codeBlock.Module; return VerifyDeniedCode(aggregateCode, result); }
protected virtual void RunNancyFx(RunOptsBase opts, RunResult result) { CompilerResults compilerResults; compilerResults = CompileNancyFx(opts, 4); RunConsole(compilerResults, result); }
private void RunConsole(RunOptsBase opts, RunResult result) { CompilerResults compilerResults; compilerResults = CompileConsole(opts, 4); RunConsole(compilerResults, result); }
protected bool CheckCodeSizeLimit(string code, ref RunResult runResult) { if (code.Length > WorkerConfiguration.Current.ExecutionCodeMaxSize) { runResult = new RunResult { IsSuccess = false, FailureType = RunResultFailureType.FatalError, FatalErrorMessage = LimitExceededException.FormatMessage(LimitType.CodeSize) }; return false; } return true; }
public RunResult Run(RunOptsBase opts) { var result = new RunResult(); result.IsSuccess = true; _consoleReader.InputLines = opts.ConsoleInputLines; if (!VerifyDeniedCodeBlock(opts, result)) { return(result); } ResolveEventHandler handler = (o, e) => CurrentDomain_AssemblyResolve(opts, e); TextWriter defaultConsoleOut = Console.Out; TextReader defaultConsoleIn = Console.In; SandboxHelper.ExecuteInFullTrust( () => { Console.SetOut(_consoleWriter); Console.SetIn(_consoleReader); }); try { AppDomain.CurrentDomain.AssemblyResolve += handler; switch (ProjectType) { case ProjectType.Console: RunConsole(opts, result); break; case ProjectType.Script: RunInteractive(opts, result); break; case ProjectType.Mvc: RunMvc(opts, result); break; default: throw new NotImplementedException(); } } catch (ThreadAbortException ex) { var consoleInputRequest = ex.ExceptionState as ConsoleInputRequest; if (consoleInputRequest != null) { result.IsSuccess = true; result.IsConsoleInputRequested = true; } else { result.IsSuccess = false; var limit = ex.ExceptionState as LimitExceededException; if (limit != null) { result.FailureType = RunResultFailureType.FatalError; result.FatalErrorMessage = LimitExceededException.FormatMessage(limit.LimitType); } } SandboxHelper.ExecuteInFullTrust(Thread.ResetAbort); } finally { //Restore Console Out just in case SandboxHelper.ExecuteInFullTrust( () => { Console.SetOut(defaultConsoleOut); Console.SetIn(defaultConsoleIn); }); // unsubscribe AppDomain.CurrentDomain.AssemblyResolve -= handler; } return(result); }
protected virtual bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result) { return(VerifyDeniedCode(((ConsoleOrScriptCodeBlock)opts.CodeBlock).CodeBlock, result)); }
protected bool VerifyDeniedCode(string code, RunResult result) { Verify.Argument.IsNotNull(code, "code"); const string DeniedCode = "PermissionSet"; if (code.IndexOf(DeniedCode, StringComparison.CurrentCultureIgnoreCase) == -1) { return true; } result.IsSuccess = false; result.FatalErrorMessage = "Using PermissionSet is not allowed due to security reasons"; result.FailureType = RunResultFailureType.FatalError; return false; }
protected virtual void RunMvc(RunOptsBase opts, RunResult result) { throw new NotImplementedException(); }
protected virtual bool VerifyDeniedCodeBlock(RunOptsBase opts, RunResult result) { return VerifyDeniedCode(((ConsoleOrScriptCodeBlock) opts.CodeBlock).CodeBlock, result); }