aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2020-12-16 20:39:02 -0600
committerSean Hall <r.sean.hall@gmail.com>2020-12-16 21:33:09 -0600
commit7ce9de201708eb3b69b7dd8dee7c0b9ded15e905 (patch)
tree902da575a81554aa6968b8dbbb2f7c400806ff3d
parent155a2a61ee57eee7735d031c489c90255b39797b (diff)
downloadwix-7ce9de201708eb3b69b7dd8dee7c0b9ded15e905.tar.gz
wix-7ce9de201708eb3b69b7dd8dee7c0b9ded15e905.tar.bz2
wix-7ce9de201708eb3b69b7dd8dee7c0b9ded15e905.zip
Canonicalize Payload/@Name.
-rw-r--r--src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs6
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/BackendHelper.cs8
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs27
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs117
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/Payload/AbsoluteName.wxs9
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/Payload/CanonicalizeName.wxs7
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/Payload/ValidName.wxs7
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/WixToolsetTest.CoreIntegration.csproj3
8 files changed, 174 insertions, 10 deletions
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
50 50
51 foreach (var payload in this.Payloads) 51 foreach (var payload in this.Payloads)
52 { 52 {
53 var normalizedPath = payload.Name.Replace('\\', '/'); 53 payload.Name = this.BackendHelper.GetCanonicalRelativePath(payload.SourceLineNumbers, "Payload", "Name", payload.Name);
54 if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../"))
55 {
56 this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(payload.SourceLineNumbers, "Payload", "Name", payload.Name));
57 }
58 54
59 // Embedded files (aka: files from binary .wixlibs) are not content files (because they are hidden 55 // Embedded files (aka: files from binary .wixlibs) are not content files (because they are hidden
60 // in the .wixlib). 56 // 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
15 public BackendHelper(IWixToolsetServiceProvider serviceProvider) 15 public BackendHelper(IWixToolsetServiceProvider serviceProvider)
16 { 16 {
17 this.Messaging = serviceProvider.GetService<IMessaging>(); 17 this.Messaging = serviceProvider.GetService<IMessaging>();
18 this.ParseHelper = serviceProvider.GetService<IParseHelper>();
18 } 19 }
19 20
20 private IMessaging Messaging { get; } 21 private IMessaging Messaging { get; }
21 22
23 private IParseHelper ParseHelper { get; }
24
22 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null) 25 public IFileTransfer CreateFileTransfer(string source, string destination, bool move, SourceLineNumber sourceLineNumbers = null)
23 { 26 {
24 var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source); 27 var sourceFullPath = this.GetValidatedFullPath(sourceLineNumbers, source);
@@ -49,6 +52,11 @@ namespace WixToolset.Core.ExtensibilityServices
49 }; 52 };
50 } 53 }
51 54
55 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath)
56 {
57 return this.ParseHelper.GetCanonicalRelativePath(sourceLineNumbers, elementName, attributeName, relativePath);
58 }
59
52 public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null) 60 public ITrackedFile TrackFile(string path, TrackedFileType type, SourceLineNumber sourceLineNumbers = null)
53 { 61 {
54 return new TrackedFile(path, type, sourceLineNumbers); 62 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
540 } 540 }
541 else if (allowRelative) 541 else if (allowRelative)
542 { 542 {
543 var normalizedPath = value.Replace('\\', '/'); 543 value = this.GetCanonicalRelativePath(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value);
544 if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../"))
545 {
546 this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
547 }
548 } 544 }
549 else if (CompilerCore.IsAmbiguousFilename(value)) 545 else if (CompilerCore.IsAmbiguousFilename(value))
550 { 546 {
@@ -705,6 +701,27 @@ namespace WixToolset.Core.ExtensibilityServices
705 } 701 }
706 } 702 }
707 703
704 public string GetCanonicalRelativePath(SourceLineNumber sourceLineNumbers, string elementName, string attributeName, string relativePath)
705 {
706 const string root = @"C:\";
707 if (!Path.IsPathRooted(relativePath))
708 {
709 var normalizedPath = Path.GetFullPath(root + relativePath);
710 if (normalizedPath.StartsWith(root))
711 {
712 var canonicalizedPath = normalizedPath.Substring(root.Length);
713 if (canonicalizedPath != relativePath)
714 {
715 this.Messaging.Write(WarningMessages.PathCanonicalized(sourceLineNumbers, elementName, attributeName, relativePath, canonicalizedPath));
716 }
717 return canonicalizedPath;
718 }
719 }
720
721 this.Messaging.Write(ErrorMessages.PayloadMustBeRelativeToCache(sourceLineNumbers, elementName, attributeName, relativePath));
722 return relativePath;
723 }
724
708 public SourceLineNumber GetSourceLineNumbers(XElement element) 725 public SourceLineNumber GetSourceLineNumbers(XElement element)
709 { 726 {
710 return Preprocessor.GetSourceLineNumbers(element); 727 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 @@
1// 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.
2
3namespace WixToolsetTest.CoreIntegration
4{
5 using System;
6 using System.IO;
7 using System.Linq;
8 using WixBuildTools.TestSupport;
9 using WixToolset.Core.Burn.Bundles;
10 using WixToolset.Core.TestPackage;
11 using WixToolset.Data;
12 using WixToolset.Data.Symbols;
13 using Xunit;
14
15 public class PayloadFixture
16 {
17 [Fact]
18 public void CanParseValidName()
19 {
20 var folder = TestData.Get(@"TestData\Payload");
21
22 using (var fs = new DisposableFileSystem())
23 {
24 var baseFolder = fs.GetFolder();
25 var intermediateFolder = Path.Combine(baseFolder, "obj");
26 var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib");
27
28 var result = WixRunner.Execute(new[]
29 {
30 "build",
31 Path.Combine(folder, "ValidName.wxs"),
32 "-intermediateFolder", intermediateFolder,
33 "-o", wixlibPath,
34 });
35
36 result.AssertSuccess();
37
38 Assert.Empty(result.Messages);
39
40 var intermediate = Intermediate.Load(wixlibPath);
41 var allSymbols = intermediate.Sections.SelectMany(s => s.Symbols);
42 var payloadSymbol = allSymbols.OfType<WixBundlePayloadSymbol>()
43 .SingleOrDefault();
44 Assert.NotNull(payloadSymbol);
45
46 var fields = payloadSymbol.Fields.Select(field => field?.Type == IntermediateFieldType.Bool
47 ? field.AsNullableNumber()?.ToString()
48 : field?.AsString())
49 .ToList();
50 Assert.Equal(@"dir\file.ext", fields[(int)WixBundlePayloadSymbolFields.Name]);
51 }
52 }
53
54 [Fact]
55 public void CanCanonicalizeName()
56 {
57 var folder = TestData.Get(@"TestData\Payload");
58
59 using (var fs = new DisposableFileSystem())
60 {
61 var baseFolder = fs.GetFolder();
62 var intermediateFolder = Path.Combine(baseFolder, "obj");
63 var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib");
64
65 var result = WixRunner.Execute(new[]
66 {
67 "build",
68 Path.Combine(folder, "CanonicalizeName.wxs"),
69 "-intermediateFolder", intermediateFolder,
70 "-o", wixlibPath,
71 });
72
73 result.AssertSuccess();
74
75 Assert.Single(result.Messages, m => m.Id == (int)WarningMessages.Ids.PathCanonicalized);
76
77 var intermediate = Intermediate.Load(wixlibPath);
78 var allSymbols = intermediate.Sections.SelectMany(s => s.Symbols);
79 var payloadSymbol = allSymbols.OfType<WixBundlePayloadSymbol>()
80 .SingleOrDefault();
81 Assert.NotNull(payloadSymbol);
82
83 var fields = payloadSymbol.Fields.Select(field => field?.Type == IntermediateFieldType.Bool
84 ? field.AsNullableNumber()?.ToString()
85 : field?.AsString())
86 .ToList();
87 Assert.Equal(@"c\d.exe", fields[(int)WixBundlePayloadSymbolFields.Name]);
88 }
89 }
90
91 [Fact]
92 public void RejectsAbsoluteName()
93 {
94 var folder = TestData.Get(@"TestData\Payload");
95
96 using (var fs = new DisposableFileSystem())
97 {
98 var baseFolder = fs.GetFolder();
99 var intermediateFolder = Path.Combine(baseFolder, "obj");
100 var wixlibPath = Path.Combine(intermediateFolder, @"test.wixlib");
101
102 var result = WixRunner.Execute(new[]
103 {
104 "build",
105 Path.Combine(folder, "AbsoluteName.wxs"),
106 "-intermediateFolder", intermediateFolder,
107 "-o", wixlibPath,
108 });
109
110 Assert.InRange(result.ExitCode, 2, int.MaxValue);
111
112 Assert.Equal(1, result.Messages.Where(m => m.Id == (int)ErrorMessages.Ids.IllegalRelativeLongFilename).Count());
113 Assert.Equal(2, result.Messages.Where(m => m.Id == (int)ErrorMessages.Ids.PayloadMustBeRelativeToCache).Count());
114 }
115 }
116 }
117}
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 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Fragment>
3 <PayloadGroup Id="AbsoluteName">
4 <Payload SourceFile="dir\file.ext" Name="\\server\share\target.file" />
5 <Payload SourceFile="dir\file.ext" Name="C:\target.file" />
6 <Payload SourceFile="dir\file.ext" Name="\dir\target.file" />
7 </PayloadGroup>
8 </Fragment>
9</Wix>
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 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Fragment>
3 <PayloadGroup Id="CanonicalizeName">
4 <Payload SourceFile="dir\file.ext" Name="a\..\c\.\d.exe" />
5 </PayloadGroup>
6 </Fragment>
7</Wix>
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 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Fragment>
3 <PayloadGroup Id="ValidName">
4 <Payload SourceFile="dir\file.ext" Name="dir\file.ext" />
5 </PayloadGroup>
6 </Fragment>
7</Wix>
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 @@
70 <Content Include="TestData\MsiTransaction\SecondX86.wxs" CopyToOutputDirectory="PreserveNewest" /> 70 <Content Include="TestData\MsiTransaction\SecondX86.wxs" CopyToOutputDirectory="PreserveNewest" />
71 <Content Include="TestData\MsiTransaction\X64AfterX86Bundle.wxs" CopyToOutputDirectory="PreserveNewest" /> 71 <Content Include="TestData\MsiTransaction\X64AfterX86Bundle.wxs" CopyToOutputDirectory="PreserveNewest" />
72 <Content Include="TestData\MsiTransaction\X86AfterX64Bundle.wxs" CopyToOutputDirectory="PreserveNewest" /> 72 <Content Include="TestData\MsiTransaction\X86AfterX64Bundle.wxs" CopyToOutputDirectory="PreserveNewest" />
73 <Content Include="TestData\Payload\AbsoluteName.wxs" CopyToOutputDirectory="PreserveNewest" />
74 <Content Include="TestData\Payload\CanonicalizeName.wxs" CopyToOutputDirectory="PreserveNewest" />
75 <Content Include="TestData\Payload\ValidName.wxs" CopyToOutputDirectory="PreserveNewest" />
73 <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> 76 <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.0.txt" CopyToOutputDirectory="PreserveNewest" />
74 <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.1.txt" CopyToOutputDirectory="PreserveNewest" /> 77 <Content Include="TestData\PatchFamilyFilter\.data\Av1.0.1.txt" CopyToOutputDirectory="PreserveNewest" />
75 <Content Include="TestData\PatchFamilyFilter\.data\Bv1.0.0.txt" CopyToOutputDirectory="PreserveNewest" /> 78 <Content Include="TestData\PatchFamilyFilter\.data\Bv1.0.0.txt" CopyToOutputDirectory="PreserveNewest" />