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
}
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);
{
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}");
}
}
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;
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.
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;
}
}
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");
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
Assert.Throws<ArgumentException>(() => 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<FileSpec>();
+ 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<ArgumentException>(() => bundler.GenerateBundle(fileSpecs));
+ }
+
[InlineData(true)]
[InlineData(false)]
[Theory]