void Write(AssemblyDefinition assemblyToPatch, NPath assemblyToPatchPath, PatchOptions patchOptions = default)
        {
            // atomic write of file with backup
            // TODO: skip backup if existing file already patched. want the .orig to only be the unpatched file.

            // write to tmp and release the lock
            var tmpPath = assemblyToPatchPath.ChangeExtension(".tmp");

            tmpPath.DeleteIfExists();
            assemblyToPatch.Write(tmpPath); // $$$ , new WriterParameters { WriteSymbols = true }); see https://github.com/jbevain/cecil/issues/421
            assemblyToPatch.Dispose();

            // TODO: peverify obviously won't work with memory written streams. also needs all the dependencies.
            // solution is to create a temp folder, write the patched dll there as well as any of its direct dependencies, and run peverify

            if ((patchOptions & PatchOptions.SkipPeVerify) == 0)
            {
                PeVerify.Verify(tmpPath);
            }

            // move the actual file to backup, and move the tmp to actual
            var backupPath = ElevatedWeaver.GetPatchBackupPathFor(assemblyToPatchPath);

            File.Replace(tmpPath, assemblyToPatchPath, backupPath);
        }
Esempio n. 2
0
        public void OneTimeSetUp()
        {
            var testAssemblyPath = Compile(GetType().Name, k_FixtureTestCode);

            var results = ElevatedWeaver.PatchAllDependentAssemblies(testAssemblyPath, PatchOptions.PatchTestAssembly);

            results.Count.ShouldBe(2);
            results.ShouldContain(new PatchResult("mscorlib", null, PatchState.IgnoredForeignAssembly));
            results.ShouldContain(new PatchResult(testAssemblyPath, ElevatedWeaver.GetPatchBackupPathFor(testAssemblyPath), PatchState.Patched));

            m_TestAssembly = AssemblyDefinition.ReadAssembly(testAssemblyPath);
            MockInjector.IsPatched(m_TestAssembly).ShouldBeTrue();
        }
Esempio n. 3
0
        public TestAssembly(string assemblyName, string testSourceCodeFile)
        {
            var outputFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            outputFolder.ShouldNotBeNull();

            m_TestAssemblyPath = Path.Combine(outputFolder, assemblyName + ".dll");

            var compiler     = new Microsoft.CSharp.CSharpCodeProvider();
            var compilerArgs = new CompilerParameters
            {
                OutputAssembly          = m_TestAssemblyPath,
                IncludeDebugInformation = true,
                CompilerOptions         = "/o- /debug+ /warn:0"
            };

            compilerArgs.ReferencedAssemblies.Add(typeof(Enumerable).Assembly.Location);

            var compilerResult = compiler.CompileAssemblyFromSource(compilerArgs, testSourceCodeFile);

            if (compilerResult.Errors.Count > 0)
            {
                var errorText = compilerResult.Errors
                                .OfType <CompilerError>()
                                .Select(e => $"({e.Line},{e.Column}): error {e.ErrorNumber}: {e.ErrorText}")
                                .Prepend("Compiler errors:")
                                .StringJoin("\n");
                throw new Exception(errorText);
            }

            m_TestAssemblyPath = compilerResult.PathToAssembly;

            PeVerify.Verify(m_TestAssemblyPath); // pre-check..sometimes we can compile code that doesn't verify

            var results = ElevatedWeaver.PatchAllDependentAssemblies(m_TestAssemblyPath, PatchTestAssembly.Yes);

            results.Count.ShouldBe(2);
            results.ShouldContain(new PatchResult("mscorlib", null, PatchState.IgnoredOutsideAllowedPaths));
            results.ShouldContain(new PatchResult(m_TestAssemblyPath, ElevatedWeaver.GetPatchBackupPathFor(m_TestAssemblyPath), PatchState.Patched));

            m_TestAssembly = AssemblyDefinition.ReadAssembly(m_TestAssemblyPath);
            MockInjector.IsPatched(m_TestAssembly).ShouldBeTrue();

            PeVerify.Verify(m_TestAssemblyPath);
        }
Esempio n. 4
0
        public static IDisposable AutoHook(string assemblyLocation)
        {
            var hookedContext = SubstitutionContext.Current;
            var thisContext   = new ElevatedSubstitutionContext(hookedContext);

            SubstitutionContext.Current = thisContext;

            // TODO: return a new IDisposable class that also contains the list of patch results, then in caller verify that against expected (don't want to go too wide)

            var patchAllDependentAssemblies = ElevatedWeaver.PatchAllDependentAssemblies(
                new NPath(assemblyLocation), PatchOptions.PatchTestAssembly).ToList();

            return(new DelegateDisposable(() =>
            {
                if (SubstitutionContext.Current != thisContext)
                {
                    throw new SubstituteException("Unexpected hook in place of ours");
                }
                SubstitutionContext.Current = hookedContext;
            }));
        }