Validate AppDomainSetup.ApplicationBase path more like .NET does
authorNiklas Therning <niklas@therning.org>
Thu, 25 Aug 2016 13:16:52 +0000 (15:16 +0200)
committerNiklas Therning <niklas@therning.org>
Thu, 25 Aug 2016 16:25:17 +0000 (18:25 +0200)
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
mcs/class/corlib/Test/System/AppDomainSetupTest.cs

index c1865f34bd366939da81af189dc94ab10a203ce4..309535cfdd7e4ba32f2f55e8d86bdf6ab733a71e 100644 (file)
@@ -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;
                }
 
index 121d1c45f10a88ceae0f80fdbbfe3575d7f7cb70..387d0318a3f45cc6eb627e3241dd6ad2bd40704a 100644 (file)
@@ -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);
                        }
                }