From 7ce9de201708eb3b69b7dd8dee7c0b9ded15e905 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 16 Dec 2020 20:39:02 -0600 Subject: Canonicalize Payload/@Name. --- .../Bundles/ProcessPayloadsCommand.cs | 6 +- .../ExtensibilityServices/BackendHelper.cs | 8 ++ .../ExtensibilityServices/ParseHelper.cs | 27 ++++- .../PayloadFixture.cs | 117 +++++++++++++++++++++ .../TestData/Payload/AbsoluteName.wxs | 9 ++ .../TestData/Payload/CanonicalizeName.wxs | 7 ++ .../TestData/Payload/ValidName.wxs | 7 ++ .../WixToolsetTest.CoreIntegration.csproj | 3 + 8 files changed, 174 insertions(+), 10 deletions(-) create mode 100644 src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Payload/AbsoluteName.wxs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Payload/CanonicalizeName.wxs create mode 100644 src/test/WixToolsetTest.CoreIntegration/TestData/Payload/ValidName.wxs (limited to 'src') diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs index 475b04b8..69c4d7c2 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs @@ -50,11 +50,7 @@ namespace WixToolset.Core.Burn.Bundles foreach (var payload in this.Payloads) { - var normalizedPath = payload.Name.Replace('\\', '/'); - if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../")) - { - this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(payload.SourceLineNumbers, "Payload", "Name", payload.Name)); - } + payload.Name = this.BackendHelper.GetCanonicalRelativePath(payload.SourceLineNumbers, "Payload", "Name", payload.Name); // Embedded files (aka: files from binary .wixlibs) are not content files (because they are hidden // in the .wixlib). diff --git a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs index e4b6e959..7b20286c 100644 --- a/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs @@ -15,10 +15,13 @@ namespace WixToolset.Core.ExtensibilityServices public BackendHelper(IWixToolsetServiceProvider serviceProvider) { this.Messaging = serviceProvider.GetService(); + this.ParseHelper = serviceProvider.GetService(); } private IMessaging Messaging { get; } + private IParseHelper ParseHelper { get; } + public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null) { var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source); @@ -49,6 +52,11 @@ namespace WixToolset.Core.ExtensibilityServices }; } + public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath) + { + return this.ParseHelper.GetCanonicalRelativePath(sourceLineNumbers, elementName, attributeName, relativePath); + } + public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null) { return new TrackedFile(path, type, sourceLineNumbers); diff --git a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs index af3f40aa..de5595e1 100644 --- a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs @@ -540,11 +540,7 @@ namespace WixToolset.Core.ExtensibilityServices } else if (allowRelative) { - var normalizedPath = value.Replace('\\', '/'); - if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../")) - { - this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); - } + value = this.GetCanonicalRelativePath(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value); } else if (CompilerCore.IsAmbiguousFilename(value)) { @@ -705,6 +701,27 @@ namespace WixToolset.Core.ExtensibilityServices } } + public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath) + { + const string root = @"C:\"; + if (!Path.IsPathRooted(relativePath)) + { + var normalizedPath = Path.GetFullPath(root + relativePath); + if (normalizedPath.StartsWith(root)) + { + var canonicalizedPath = normalizedPath.Substring(root.Length); + if (canonicalizedPath != relativePath) + { + this.Messaging.Write(WarningMessages.PathCanonicalized(sourceLineNumbers, elementName, attributeName, relativePath, canonicalizedPath)); + } + return canonicalizedPath; + } + } + + this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, elementName, attributeName, relativePath)); + return relativePath; + } + public SourceLineNumber GetSourceLineNumbers(XElement element) { return Preprocessor.GetSourceLineNumbers(element); diff --git a/src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs b/src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs new file mode 100644 index 00000000..4568f93f --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs @@ -0,0 +1,117 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolsetTest.CoreIntegration +{ + using System; + using System.IO; + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.Burn.Bundles; + using WixToolset.Core.TestPackage; + using WixToolset.Data; + using WixToolset.Data.Symbols; + using Xunit; + + public class PayloadFixture + { + [Fact] + public void CanParseValidName() + { + var folder = TestData.Get(@"TestData\Payload"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "ValidName.wxs"), + "-intermediateFolder", intermediateFolder, + "-o", wixlibPath, + }); + + result.AssertSuccess(); + + Assert.Empty(result.Messages); + + var intermediate = Intermediate.Load(wixlibPath); + var allSymbols = intermediate.Sections.SelectMany(s => s.Symbols); + var payloadSymbol = allSymbols.OfType() + .SingleOrDefault(); + Assert.NotNull(payloadSymbol); + + var fields = payloadSymbol.Fields.Select(field => field?.Type == IntermediateFieldType.Bool + ? field.AsNullableNumber()?.ToString() + : field?.AsString()) + .ToList(); + Assert.Equal(@"dir\file.ext", fields[(int)WixBundlePayloadSymbolFields.Name]); + } + } + + [Fact] + public void CanCanonicalizeName() + { + var folder = TestData.Get(@"TestData\Payload"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "CanonicalizeName.wxs"), + "-intermediateFolder", intermediateFolder, + "-o", wixlibPath, + }); + + result.AssertSuccess(); + + Assert.Single(result.Messages, m => m.Id == (int)WarningMessages.Ids.PathCanonicalized); + + var intermediate = Intermediate.Load(wixlibPath); + var allSymbols = intermediate.Sections.SelectMany(s => s.Symbols); + var payloadSymbol = allSymbols.OfType() + .SingleOrDefault(); + Assert.NotNull(payloadSymbol); + + var fields = payloadSymbol.Fields.Select(field => field?.Type == IntermediateFieldType.Bool + ? field.AsNullableNumber()?.ToString() + : field?.AsString()) + .ToList(); + Assert.Equal(@"c\d.exe", fields[(int)WixBundlePayloadSymbolFields.Name]); + } + } + + [Fact] + public void RejectsAbsoluteName() + { + var folder = TestData.Get(@"TestData\Payload"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib"); + + var result = WixRunner.Execute(new[] + { + "build", + Path.Combine(folder, "AbsoluteName.wxs"), + "-intermediateFolder", intermediateFolder, + "-o", wixlibPath, + }); + + Assert.InRange(result.ExitCode, 2, int.MaxValue); + + Assert.Equal(1, result.Messages.Where(m => m.Id == (int)ErrorMessages.Ids.IllegalRelativeLongFilename).Count()); + Assert.Equal(2, result.Messages.Where(m => m.Id == (int)ErrorMessages.Ids.PayloadMustBeRelativeToCache).Count()); + } + } + } +} diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/AbsoluteName.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/AbsoluteName.wxs new file mode 100644 index 00000000..dc94d688 --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/AbsoluteName.wxs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/CanonicalizeName.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/CanonicalizeName.wxs new file mode 100644 index 00000000..544b80ec --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/CanonicalizeName.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/ValidName.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/ValidName.wxs new file mode 100644 index 00000000..9c37a27d --- /dev/null +++ b/src/test/WixToolsetTest.CoreIntegration/TestData/Payload/ValidName.wxs @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj index ff04e65f..9ebf1e5c 100644 --- a/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj +++ b/src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj @@ -70,6 +70,9 @@ + + + -- cgit v1.2.3-55-g6feb