From 76709e28e052c0b9708495153ddfd5303dc6623f Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 7 Jul 2022 12:32:55 -0700 Subject: Enable parsing invalid WixVersions Fixes 6775 --- src/api/wix/WixToolset.Data/WixVersion.cs | 49 +++++- .../wix/test/WixToolsetTest.Data/WixVerFixture.cs | 194 ++++++++++++++++++--- 2 files changed, 214 insertions(+), 29 deletions(-) (limited to 'src/api') diff --git a/src/api/wix/WixToolset.Data/WixVersion.cs b/src/api/wix/WixToolset.Data/WixVersion.cs index ab68b55a..a0de7a10 100644 --- a/src/api/wix/WixToolset.Data/WixVersion.cs +++ b/src/api/wix/WixToolset.Data/WixVersion.cs @@ -39,6 +39,11 @@ namespace WixToolset.Data /// public uint Revision { get; set; } + /// + /// Gets or sets whether the version did not parse correctly. + /// + public bool Invalid { get; set; } + /// /// Gets or sets whether the major version was defined. /// @@ -70,14 +75,13 @@ namespace WixToolset.Data public string Metadata { get; set; } /// - /// Tries to parse a string value into a valid WixVersion. + /// Parse a string value into a WixVersion. The returned version may be invalid. /// /// String value to parse into a version. - /// Parsed version. - /// True if the version was successfully parsed, or false otherwise. - public static bool TryParse(string parse, out WixVersion version) + /// Parsed version. + public static WixVersion Parse(string parse) { - version = new WixVersion(); + var version = new WixVersion(); var labels = new List(); var start = 0; @@ -286,14 +290,45 @@ namespace WixToolset.Data } } + version.Labels = labels.Count == 0 ? null : labels.ToArray(); + if (invalid) + { + // If the prefix was parsed but the rest of the version was + // invalid, store the full invalid version in the Metadata + // and clear the prefix. + if (version.Prefix.HasValue && partBegin == 1) + { + version.Prefix = null; + version.Metadata = parse; + } + else // store the remaining invalid content in Metadata. + { + version.Metadata = (partBegin < end) ? parse.Substring(partBegin) : String.Empty; + } + + version.Invalid = true; + } + + return version; + } + + /// + /// Tries to parse a string value into a valid WixVersion. + /// + /// String value to parse into a version. + /// Parsed version. + /// True if the version was successfully parsed, or false otherwise. + public static bool TryParse(string parse, out WixVersion version) + { + version = WixVersion.Parse(parse); + + if (version.Invalid) { version = null; return false; } - version.Labels = labels.Count == 0 ? null : labels.ToArray(); - return true; } } diff --git a/src/api/wix/test/WixToolsetTest.Data/WixVerFixture.cs b/src/api/wix/test/WixToolsetTest.Data/WixVerFixture.cs index ffa3213a..56c72896 100644 --- a/src/api/wix/test/WixToolsetTest.Data/WixVerFixture.cs +++ b/src/api/wix/test/WixToolsetTest.Data/WixVerFixture.cs @@ -3,6 +3,7 @@ namespace WixToolsetTest.Data { using System; + using System.Linq; using WixToolset.Data; using Xunit; @@ -15,6 +16,14 @@ namespace WixToolsetTest.Data Assert.Null(version); } + [Fact] + public void CanParseEmptyStringAsInvalidVersion() + { + var version = WixVersion.Parse(String.Empty); + Assert.Empty(version.Metadata); + Assert.True(version.Invalid); + } + [Fact] public void CannotParseInvalidStringAsVersion() { @@ -22,6 +31,14 @@ namespace WixToolsetTest.Data Assert.Null(version); } + [Fact] + public void CanParseInvalidStringAsInvalidVersion() + { + var version = WixVersion.Parse("invalid"); + Assert.Equal("invalid", version.Metadata); + Assert.True(version.Invalid); + } + [Fact] public void CanParseFourPartVersion() { @@ -37,6 +54,7 @@ namespace WixToolsetTest.Data Assert.True(version.HasRevision); Assert.Null(version.Labels); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -54,6 +72,7 @@ namespace WixToolsetTest.Data Assert.False(version.HasRevision); Assert.Null(version.Labels); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -71,6 +90,7 @@ namespace WixToolsetTest.Data Assert.True(version.HasRevision); Assert.Null(version.Labels); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -86,9 +106,10 @@ namespace WixToolsetTest.Data Assert.True(version.HasMinor); Assert.False(version.HasPatch); Assert.False(version.HasRevision); - Assert.Equal("19", version.Labels[0].Label); - Assert.Equal((uint)19, version.Labels[0].Numeric); + Assert.Equal(new[] { "19" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { 19 }, version.Labels.Select(l => l.Numeric).ToArray()); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -104,11 +125,10 @@ namespace WixToolsetTest.Data Assert.True(version.HasMinor); Assert.False(version.HasPatch); Assert.False(version.HasRevision); - Assert.Equal("2", version.Labels[0].Label); - Assert.Equal((uint)2, version.Labels[0].Numeric); - Assert.Equal("0", version.Labels[1].Label); - Assert.Equal((uint)0, version.Labels[1].Numeric); + Assert.Equal(new[] { "2", "0" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { 2, 0 }, version.Labels.Select(l => l.Numeric).ToArray()); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -124,9 +144,10 @@ namespace WixToolsetTest.Data Assert.True(version.HasMinor); Assert.True(version.HasPatch); Assert.False(version.HasRevision); - Assert.Equal("a", version.Labels[0].Label); - Assert.Null(version.Labels[0].Numeric); + Assert.Equal(new[] { "a" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { null }, version.Labels.Select(l => l.Numeric).ToArray()); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -142,11 +163,10 @@ namespace WixToolsetTest.Data Assert.True(version.HasMinor); Assert.False(version.HasPatch); Assert.False(version.HasRevision); - Assert.Equal("a", version.Labels[0].Label); - Assert.Null(version.Labels[0].Numeric); - Assert.Equal("000", version.Labels[1].Label); - Assert.Equal((uint)0, version.Labels[1].Numeric); + Assert.Equal(new[] { "a", "000" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { null, 0 }, version.Labels.Select(l => l.Numeric).ToArray()); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -164,6 +184,7 @@ namespace WixToolsetTest.Data Assert.False(version.HasRevision); Assert.Null(version.Labels); Assert.Equal("abcd", version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -175,6 +196,18 @@ namespace WixToolsetTest.Data Assert.Null(version); } + [Fact] + public void CanParseUnexpectedContentAsInvalidMetadata() + { + var version = WixVersion.Parse("1.2.3.abcd"); + Assert.Equal("abcd", version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("1.2.3.-abcd"); + Assert.Equal("-abcd", version.Metadata); + Assert.True(version.Invalid); + } + [Fact] public void CanParseLeadingPrefix() { @@ -190,6 +223,7 @@ namespace WixToolsetTest.Data Assert.True(version.HasRevision); Assert.Null(version.Labels); Assert.Null(version.Metadata); + Assert.False(version.Invalid); Assert.True(WixVersion.TryParse("V100.200.300.400", out var version2)); Assert.Equal('V', version2.Prefix); @@ -203,6 +237,7 @@ namespace WixToolsetTest.Data Assert.True(version.HasRevision); Assert.Null(version2.Labels); Assert.Null(version2.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -220,6 +255,7 @@ namespace WixToolsetTest.Data Assert.True(version.HasRevision); Assert.Null(version.Labels); Assert.Null(version.Metadata); + Assert.False(version.Invalid); } [Fact] @@ -229,6 +265,24 @@ namespace WixToolsetTest.Data Assert.Null(version); } + [Fact] + public void CanParseInvalidTooLargeNumbers() + { + var version = WixVersion.Parse("4294967296.4294967296.4294967296.4294967296"); + Assert.Equal(0U, version.Major); + Assert.Equal("4294967296.4294967296.4294967296.4294967296", version.Metadata); + Assert.True(version.Invalid); + } + + [Fact] + public void CanParseInvalidTooLargeNumbersWithPrefix() + { + var version = WixVersion.Parse("v4294967296.4294967296.4294967296.4294967296"); + Assert.Equal("v4294967296.4294967296.4294967296.4294967296", version.Metadata); + Assert.Null(version.Prefix); + Assert.True(version.Invalid); + } + [Fact] public void CanParseLabelsWithMetadata() { @@ -242,17 +296,113 @@ namespace WixToolsetTest.Data Assert.True(version.HasMinor); Assert.True(version.HasPatch); Assert.True(version.HasRevision); - Assert.Equal("a", version.Labels[0].Label); - Assert.Null(version.Labels[0].Numeric); - Assert.Equal("b", version.Labels[1].Label); - Assert.Null(version.Labels[1].Numeric); - Assert.Equal("c", version.Labels[2].Label); - Assert.Null(version.Labels[2].Numeric); - Assert.Equal("d", version.Labels[3].Label); - Assert.Null(version.Labels[3].Numeric); - Assert.Equal("5", version.Labels[4].Label); - Assert.Equal((uint)5, version.Labels[4].Numeric); + Assert.Equal(new[] { "a", "b", "c", "d", "5" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { null, null, null, null, 5 }, version.Labels.Select(l => l.Numeric).ToArray()); Assert.Equal("abc123", version.Metadata); + Assert.False(version.Invalid); + } + + [Fact] + public void CanParseVersionWithTrailingDotsAsInvalid() + { + var version = WixVersion.Parse("."); + Assert.Null(version.Prefix); + Assert.Equal(0U, version.Major); + Assert.Equal(0U, version.Minor); + Assert.Equal(0U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Null(version.Labels); + Assert.False(version.HasMajor); + Assert.False(version.HasMinor); + Assert.False(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(".", version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("1."); + Assert.Null(version.Prefix); + Assert.Equal(1U, version.Major); + Assert.Equal(0U, version.Minor); + Assert.Equal(0U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Null(version.Labels); + Assert.True(version.HasMajor); + Assert.False(version.HasMinor); + Assert.False(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(String.Empty, version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("2.1."); + Assert.Null(version.Prefix); + Assert.Equal(2U, version.Major); + Assert.Equal(1U, version.Minor); + Assert.Equal(0U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Null(version.Labels); + Assert.True(version.HasMajor); + Assert.True(version.HasMinor); + Assert.False(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(String.Empty, version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("3.2.1."); + Assert.Null(version.Prefix); + Assert.Equal(3U, version.Major); + Assert.Equal(2U, version.Minor); + Assert.Equal(1U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Null(version.Labels); + Assert.True(version.HasMajor); + Assert.True(version.HasMinor); + Assert.True(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(String.Empty, version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("4.3.2.1."); + Assert.Null(version.Prefix); + Assert.Equal(4U, version.Major); + Assert.Equal(3U, version.Minor); + Assert.Equal(2U, version.Patch); + Assert.Equal(1U, version.Revision); + Assert.Null(version.Labels); + Assert.True(version.HasMajor); + Assert.True(version.HasMinor); + Assert.True(version.HasPatch); + Assert.True(version.HasRevision); + Assert.Equal(String.Empty, version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("5-."); + Assert.Null(version.Prefix); + Assert.Equal(5U, version.Major); + Assert.Equal(0U, version.Minor); + Assert.Equal(0U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Null(version.Labels); + Assert.True(version.HasMajor); + Assert.False(version.HasMinor); + Assert.False(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(".", version.Metadata); + Assert.True(version.Invalid); + + version = WixVersion.Parse("6-a."); + Assert.Null(version.Prefix); + Assert.Equal(6U, version.Major); + Assert.Equal(0U, version.Minor); + Assert.Equal(0U, version.Patch); + Assert.Equal(0U, version.Revision); + Assert.Equal(new[] { "a" }, version.Labels.Select(l => l.Label).ToArray()); + Assert.Equal(new uint?[] { null }, version.Labels.Select(l => l.Numeric).ToArray()); + Assert.True(version.HasMajor); + Assert.False(version.HasMinor); + Assert.False(version.HasPatch); + Assert.False(version.HasRevision); + Assert.Equal(String.Empty, version.Metadata); + Assert.True(version.Invalid); } } } -- cgit v1.2.3-55-g6feb