From 83e7e0822ee442560983136c069bb4ef1da8bc8f Mon Sep 17 00:00:00 2001 From: Niklas Therning Date: Thu, 25 Aug 2016 15:16:52 +0200 Subject: [PATCH] Validate AppDomainSetup.ApplicationBase path more like .NET does On Windows we should check the path for invalid characters. Also expand relative paths set using file:// URLs like .NET does. This patch also removes the code which prepends "//" on Windows when a file:// URL is given as .NET doesn't seem to do that in more recent versions. --- mcs/class/corlib/System/AppDomainSetup.cs | 16 ++- .../corlib/Test/System/AppDomainSetupTest.cs | 105 +++++++++++------- 2 files changed, 78 insertions(+), 43 deletions(-) diff --git a/mcs/class/corlib/System/AppDomainSetup.cs b/mcs/class/corlib/System/AppDomainSetup.cs index c1865f34bd3..309535cfdd7 100644 --- a/mcs/class/corlib/System/AppDomainSetup.cs +++ b/mcs/class/corlib/System/AppDomainSetup.cs @@ -36,6 +36,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; +using System.Security.Permissions; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Hosting; @@ -139,14 +140,19 @@ namespace System appBase = appBase.Substring (7); if (Path.DirectorySeparatorChar != '/') appBase = appBase.Replace ('/', Path.DirectorySeparatorChar); - if (Environment.IsRunningOnWindows) { - // Under Windows prepend "//" to indicate it's a local file - appBase = "//" + appBase; + } + appBase = Path.GetFullPath (appBase); + + if (Path.DirectorySeparatorChar != '/') { + bool isExtendedPath = appBase.StartsWith (@"\\?\", StringComparison.Ordinal); + if (appBase.IndexOf (':', isExtendedPath ? 6 : 2) != -1) { + throw new NotSupportedException ("The given path's format is not supported."); } - } else { - appBase = Path.GetFullPath (appBase); } + // Trigger a validation of the path + new FileIOPermission (FileIOPermissionAccess.PathDiscovery, appBase); + return appBase; } diff --git a/mcs/class/corlib/Test/System/AppDomainSetupTest.cs b/mcs/class/corlib/Test/System/AppDomainSetupTest.cs index 121d1c45f10..387d0318a3f 100644 --- a/mcs/class/corlib/Test/System/AppDomainSetupTest.cs +++ b/mcs/class/corlib/Test/System/AppDomainSetupTest.cs @@ -23,8 +23,12 @@ namespace MonoTests.System private bool RunningOnWindows { get { - int os = (int)Environment.OSVersion.Platform; - return (os != 4); + return Path.DirectorySeparatorChar == '\\'; + } + } + private bool RunningOnMono { + get { + return (Type.GetType ("System.MonoType", false) != null); } } @@ -72,22 +76,18 @@ namespace MonoTests.System [Test] public void ApplicationBase1 () { - string expected_path = tmpPath.Replace(@"\", @"/"); + string expected_path = tmpPath; AppDomainSetup setup = new AppDomainSetup (); - string fileUri = "file://" + expected_path; + string fileUri = "file://" + tmpPath.Replace(@"\", @"/"); setup.ApplicationBase = fileUri; - // with MS 1.1 SP1 the expected_path starts with "//" but this make - // sense only under Windows (i.e. reversed \\ for local files) - if (RunningOnWindows) - expected_path = "//" + expected_path; try { - // under 2.0 the NotSupportedException is throw when getting + // under .NET the NotSupportedException is throw when getting // (and not setting) the ApplicationBase property Assert.AreEqual (expected_path, setup.ApplicationBase); } catch (NotSupportedException) { - // however the path is invalid only on Windows - if (!RunningOnWindows) + // however the path is invalid only on .NET + if (RunningOnMono) throw; } } @@ -114,16 +114,17 @@ namespace MonoTests.System { AppDomainSetup setup = new AppDomainSetup (); setup.ApplicationBase = "lala:la"; - try { - // under 2.0 the NotSupportedException is throw when getting - // (and not setting) the ApplicationBase property + if (!RunningOnWindows) { Assert.AreEqual (Path.GetFullPath ("lala:la"), setup.ApplicationBase); - } - catch (NotSupportedException) { - // however the path is invalid only on Windows - // (same exceptions as Path.GetFullPath) - if (!RunningOnWindows) - throw; + } else { + // On Windows we expect a NotSupportedException to be thrown because + // of the illegal character (:) in the path + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); + } + catch (NotSupportedException) { + // Expected + } } } @@ -133,16 +134,18 @@ namespace MonoTests.System // This is failing because of (probably) a windows-ism, so don't worry AppDomainSetup setup = new AppDomainSetup (); setup.ApplicationBase = "file:///lala:la"; - try { - // under 2.0 the NotSupportedException is throw when getting - // (and not setting) the ApplicationBase property - Assert.AreEqual ("/lala:la", setup.ApplicationBase); - } - catch (NotSupportedException) { - // however the path is invalid only on Windows - // (same exceptions as Path.GetFullPath) - if (!RunningOnWindows) - throw; + string expected = "/lala:la"; + if (!RunningOnWindows) { + Assert.AreEqual (expected, setup.ApplicationBase); + } else { + // On Windows we expect a NotSupportedException to be thrown because + // of the illegal character (:) in the path + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); + } + catch (NotSupportedException) { + // Expected + } } } @@ -153,19 +156,45 @@ namespace MonoTests.System setup.ApplicationBase = "la?lala"; // paths containing "?" are *always* bad on Windows // but are legal for linux so we return a full path - if (RunningOnWindows) { + if (!RunningOnWindows) { + Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase); + } else { + // On Windows we expect a ArgumentException to be thrown because + // of the illegal character (?) in the path try { - // ArgumentException is throw when getting - // (and not setting) the ApplicationBase property - Assert.Fail ("setup.ApplicationBase returned :" + setup.ApplicationBase); + Assert.Fail ("ArgumentException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); } catch (ArgumentException) { + // Expected + } + } + } + + [Test] + public void ApplicationBase7 () + { + if (RunningOnWindows) { + // Extended paths are Windows only + AppDomainSetup setup = new AppDomainSetup (); + string expected = @"\\?\" + curDir; + setup.ApplicationBase = expected; + Assert.AreEqual (expected, setup.ApplicationBase); + } + } + + [Test] + public void ApplicationBase8 () + { + if (RunningOnWindows) { + // Extended paths are Windows only + AppDomainSetup setup = new AppDomainSetup (); + setup.ApplicationBase = @"\\?\C:\lala:la"; + try { + Assert.Fail ("NotSupportedException expected but setup.ApplicationBase returned:" + setup.ApplicationBase); } - catch (Exception e) { - Assert.Fail ("Unexpected exception: " + e.ToString ()); + catch (NotSupportedException) { + // Expected } - } else { - Assert.AreEqual (Path.GetFullPath ("la?lala"), setup.ApplicationBase); } } -- 2.25.1