From: Swaroop Sridhar Date: Sun, 16 Jun 2019 00:41:28 +0000 (-0700) Subject: Bundler: Check for duplicate file entries. (dotnet/core-setup#6799) X-Git-Tag: submit/tizen/20210909.063632~11032^2~162 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=937026fb5780be979e679a1a5076895dbdda92b9;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Bundler: Check for duplicate file entries. (dotnet/core-setup#6799) If the input to the bundler contains multiple entries with the same relative path, we currently generate a bundle with a larger size with some unusable files. Therefore, check this condition when generating bundles, and throw an error. The extractor also checks this condition when extracting malformed bundles. Commit migrated from https://github.com/dotnet/core-setup/commit/f1c72ba8603d2b13484f37f62b5987564a48be12 --- diff --git a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs index 67a478f..fb15489 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Bundler.cs @@ -156,7 +156,12 @@ namespace Microsoft.NET.HostModel.Bundle } catch (InvalidOperationException) { - throw new ArgumentException("Input must uniquely specify the host binary"); + throw new ArgumentException("Invalid input specification: Must specify the host binary"); + } + + if(fileSpecs.GroupBy(file => file.BundleRelativePath).Where(g => g.Count() > 1).Any()) + { + throw new ArgumentException("Invalid input specification: Found multiple entries with the same BundleRelativePath"); } string bundlePath = Path.Combine(OutputDir, HostName); @@ -187,8 +192,7 @@ namespace Microsoft.NET.HostModel.Bundle { FileType type = InferType(fileSpec.BundleRelativePath, file); long startOffset = AddToBundle(bundle, file, type); - FileEntry entry = new FileEntry(type, fileSpec.BundleRelativePath, startOffset, file.Length); - BundleManifest.Files.Add(entry); + FileEntry entry = BundleManifest.AddEntry(type, fileSpec.BundleRelativePath, startOffset, file.Length); trace.Log($"Embed: {entry}"); } } diff --git a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs index f24837a..907c869 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs @@ -71,6 +71,13 @@ namespace Microsoft.NET.HostModel.Bundle BundleID = bundleID; } + public FileEntry AddEntry(FileType type, string relativePath, long offset, long size) + { + FileEntry entry = new FileEntry(type, relativePath, offset, size); + Files.Add(entry); + return entry; + } + public long Write(BinaryWriter writer) { long startOffset = writer.BaseStream.Position; @@ -104,7 +111,7 @@ namespace Microsoft.NET.HostModel.Bundle string signature = reader.ReadString(); if (!signature.Equals(Signature)) { - throw new BundleException("Invalid Bundle"); + throw new BundleException("Extraction failed: Invalid Bundle"); } // The manifest header offset resides just behind the signature. @@ -130,6 +137,11 @@ namespace Microsoft.NET.HostModel.Bundle manifest.Files.Add(FileEntry.Read(reader)); } + if (manifest.Files.GroupBy(file => file.RelativePath).Where(g => g.Count() > 1).Any()) + { + throw new BundleException("Extraction failed: Found multiple entries with the same bundle-relative-path"); + } + return manifest; } } diff --git a/src/installer/test/BundleTests/Helpers/BundleHelper.cs b/src/installer/test/BundleTests/Helpers/BundleHelper.cs index 8139d6e..71d18fe 100644 --- a/src/installer/test/BundleTests/Helpers/BundleHelper.cs +++ b/src/installer/test/BundleTests/Helpers/BundleHelper.cs @@ -10,11 +10,27 @@ namespace BundleTests.Helpers public static class BundleHelper { public const string DotnetBundleExtractBaseEnvVariable = "DOTNET_BUNDLE_EXTRACT_BASE_DIR"; + + public static string GetHostPath(TestProjectFixture fixture) + { + return Path.Combine(GetPublishPath(fixture), GetHostName(fixture)); + } + + public static string GetAppPath(TestProjectFixture fixture) + { + return Path.Combine(GetPublishPath(fixture), GetAppName(fixture)); + } + public static string GetHostName(TestProjectFixture fixture) { return Path.GetFileName(fixture.TestProject.AppExe); } + public static string GetAppName(TestProjectFixture fixture) + { + return Path.GetFileName(fixture.TestProject.AppDll); + } + public static string GetPublishPath(TestProjectFixture fixture) { return Path.Combine(fixture.TestProject.ProjectDirectory, "publish"); diff --git a/src/installer/test/BundleTests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs b/src/installer/test/BundleTests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs index c823f5a..5773777 100644 --- a/src/installer/test/BundleTests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs +++ b/src/installer/test/BundleTests/Microsoft.NET.HostModel.Bundle.Tests/BundlerConsistencyTests.cs @@ -50,7 +50,6 @@ namespace Microsoft.NET.HostModel.Tests var hostName = BundleHelper.GetHostName(fixture); var appName = Path.GetFileNameWithoutExtension(hostName); - string publishPath = BundleHelper.GetPublishPath(fixture); var bundleDir = BundleHelper.GetBundleDir(fixture); // Generate a file specification without the apphost @@ -63,6 +62,24 @@ namespace Microsoft.NET.HostModel.Tests Assert.Throws(() => bundler.GenerateBundle(fileSpecs)); } + [Fact] + public void TestWithDuplicateEntriesFails() + { + var fixture = sharedTestState.TestFixture.Copy(); + + var hostName = BundleHelper.GetHostName(fixture); + var bundleDir = BundleHelper.GetBundleDir(fixture); + + // Generate a file specification with duplicate entries + var fileSpecs = new List(); + fileSpecs.Add(new FileSpec(BundleHelper.GetHostPath(fixture), BundleHelper.GetHostName(fixture))); + fileSpecs.Add(new FileSpec(BundleHelper.GetAppPath(fixture), "app.repeat")); + fileSpecs.Add(new FileSpec(BundleHelper.GetAppPath(fixture), "app.repeat")); + + Bundler bundler = new Bundler(hostName, bundleDir.FullName); + Assert.Throws(() => bundler.GenerateBundle(fileSpecs)); + } + [InlineData(true)] [InlineData(false)] [Theory]