Example #1
0
        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())));
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
        }
Example #4
0
        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());
        }