public void ValidateSharedCompilation(string sourceFilename, [CanBeNull] string targetType, [CanBeNull] string outputAssembly) { var managedProject = GetCscProject(sourceFilename, targetType, outputAssembly); var program = GetHelloWorldProgram(); var config = (CommandLineConfiguration)Build(useSharedCompilation: true) .AddSpec(R("ManagedProject.csproj"), managedProject) .AddFile(R("Program.cs"), program) .PersistSpecsAndGetConfiguration(); config.Sandbox.FileSystemMode = FileSystemMode.RealAndMinimalPipGraph; config.Sandbox.LogObservedFileAccesses = true; var listener = new FileAccessDetoursListenerCollector(PathTable); var result = RunEngineWithConfig(config, detoursListener: listener); Assert.True(result.IsSuccess); // Let's verify now that accesses were properly compensated. We should see the (single) source // file and the output + pdb as outputs var allAccesses = listener.GetAllFileAccessPaths().Select(path => path.ToUpperInvariant()); Assert.True(allAccesses.Any(input => input.Contains(sourceFilename.ToUpperInvariant()))); // If the output assembly is not specified, there should be an output reported anyway, with a // filename (modulo extension) equal to the source if (outputAssembly == null) { outputAssembly = Path.ChangeExtension(sourceFilename, null); } Assert.True(allAccesses.Any(output => output.Contains(outputAssembly.ToUpperInvariant()))); Assert.True(allAccesses.Any(output => output.Contains(Path.ChangeExtension(outputAssembly, ".pdb").ToUpperInvariant()))); }
public void MaskedReportAugmentedAccessIsNotReported(bool reportFileAccesses) { var fam = new FileAccessManifest( Context.PathTable, childProcessesToBreakawayFromSandbox: new[] { TestProcessToolName }) { FailUnexpectedFileAccesses = false, ReportUnexpectedFileAccesses = true, ReportFileAccesses = reportFileAccesses }; var basePath = TestBinRootPath.Combine(Context.PathTable, "foo"); var output1 = CreateOutputFileArtifact(basePath); var output2 = CreateOutputFileArtifact(basePath); // We mask reporting accesses for output1 and enable it for output2 fam.AddScope(output1.Path, ~FileAccessPolicy.ReportAccess, FileAccessPolicy.AllowAll); fam.AddScope(output2.Path, FileAccessPolicy.MaskNothing, FileAccessPolicy.AllowAll | FileAccessPolicy.ReportAccess); var collector = new FileAccessDetoursListenerCollector(Context.PathTable); var info = ToProcessInfo( ToProcess( Operation.AugmentedWrite(output1), Operation.AugmentedWrite(output2)), fileAccessManifest: fam, detoursListener: collector); var result = RunProcess(info).GetAwaiter().GetResult(); XAssert.AreEqual(0, result.ExitCode); // We should get a single explicit access with output2, since output1 shouldn't be reported var accessPath = result.ExplicitlyReportedFileAccesses.Single(rfa => rfa.Method == FileAccessStatusMethod.TrustedTool).ManifestPath; XAssert.AreEqual(output2.Path, accessPath); // We should get both accesses as part of the (optional) FileAccess on request if (reportFileAccesses) { var allTrustedAcceses = result.FileAccesses.Where(rfa => rfa.Method == FileAccessStatusMethod.TrustedTool).Select(rfa => rfa.ManifestPath); XAssert.Contains(allTrustedAcceses, output1.Path, output2.Path); } else { // Make sure the access related to output1 is not actually reported, and the only one the listener got is output2 XAssert.Contains(collector.GetFileAccessPaths(), output2.Path); XAssert.ContainsNot(collector.GetFileAccessPaths(), output1.Path); } }
private FileAccessDetoursListenerCollector RunManagedCompilation( bool useSharedCompilation, out string absolutePathToReference, out AbsolutePath usedTempDirectory, string additionalArgs = null) { // We pass the executing assembly to the compiler call just as a way to pass an arbitrary valid assembly (and not because there are any required dependencies on it) absolutePathToReference = Assembly.GetExecutingAssembly().Location; // We just use the assembly name, but add the assembly directory to the collection of additional paths var managedProject = GetCscProject( "Program.cs", "exe", "Out.exe", $@"References='{Path.GetFileName(absolutePathToReference)}' AdditionalLibPaths='{Path.GetDirectoryName(absolutePathToReference)}' NoStandardLib='false' NoConfig='false' {additionalArgs ?? string.Empty}"); var program = GetHelloWorldProgram(); var config = (CommandLineConfiguration)Build(useSharedCompilation: useSharedCompilation) .AddSpec(R("ManagedProject.csproj"), managedProject) .AddFile(R("Program.cs"), program) .PersistSpecsAndGetConfiguration(); config.Sandbox.FileSystemMode = FileSystemMode.RealAndMinimalPipGraph; config.Sandbox.LogObservedFileAccesses = true; var listener = new FileAccessDetoursListenerCollector(PathTable); var result = RunEngineWithConfig(config, detoursListener: listener); Assert.True(result.IsSuccess); // The whole compilation is performed by a single pip var process = (Process)result.EngineState.PipGraph.RetrievePipsOfType(PipType.Process).Single(); usedTempDirectory = process.TempDirectory; return(listener); }
public void AugmentedAccessPathsAreCanonicalized() { var fam = new FileAccessManifest( Context.PathTable, childProcessesToBreakawayFromSandbox: new[] { TestProcessToolName }) { FailUnexpectedFileAccesses = false, ReportUnexpectedFileAccesses = true, ReportFileAccesses = true }; var basePath = TestBinRootPath.Combine(Context.PathTable, "foo").Combine(Context.PathTable, "bar"); // Let's create a path that is equivalent to base path but it is constructed with '..' string nonCanonicalBasePath = Path.Combine(basePath.ToString(Context.PathTable), "..", "bar"); var source = CreateSourceFile(basePath); var output = CreateOutputFileArtifact(basePath); // Now create non-canonical paths for source and output string nonCanonicalSource = Path.Combine(nonCanonicalBasePath, source.Path.GetName(Context.PathTable).ToString(Context.StringTable)); string nonCanonicalOutput = Path.Combine(nonCanonicalBasePath, output.Path.GetName(Context.PathTable).ToString(Context.StringTable)); var collector = new FileAccessDetoursListenerCollector(Context.PathTable); var info = ToProcessInfo( ToProcess( Operation.AugmentedRead(nonCanonicalSource), Operation.AugmentedWrite(nonCanonicalOutput)), fileAccessManifest: fam, detoursListener: collector); var result = RunProcess(info).GetAwaiter().GetResult(); XAssert.AreEqual(0, result.ExitCode); // Let's check the raw paths reported by detours to make sure they are canonicalized var allRawPaths = collector.GetAllFileAccessPaths().Select(path => path.ToUpperInvariant()); XAssert.Contains(allRawPaths, source.Path.ToString(Context.PathTable).ToUpperInvariant(), output.Path.ToString(Context.PathTable).ToUpperInvariant()); }