Blob Blame History Raw
From 65a19e18d7d4b94f50772bd3118c0b9868766af5 Mon Sep 17 00:00:00 2001
From: Maryam Ariyan <maryam.ariyan@microsoft.com>
Date: Fri, 7 Sep 2018 10:53:25 -0700
Subject: [PATCH] Fixes extract out of directory by ensuring trailing separator
 for nested paths.

Related to PR #32127
---
 .../System/IO/Compression/ZipFileExtensions.cs  |  2 ++
 .../tests/ZipFileConvenienceMethods.cs          | 17 +++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/src/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.cs b/src/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.cs
index 3fef7883c953..c749c8250f9c 100644
--- a/src/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.cs
+++ b/src/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.cs
@@ -160,6 +160,8 @@ public static void ExtractToDirectory(this ZipArchive source, string destination
             // Note that this will give us a good DirectoryInfo even if destinationDirectoryName exists:
             DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
             string destinationDirectoryFullPath = di.FullName;
+            if (!destinationDirectoryFullPath.EndsWith(Path.DirectorySeparatorChar))
+                destinationDirectoryFullPath += Path.DirectorySeparatorChar;
 
             foreach (ZipArchiveEntry entry in source.Entries)
             {
diff --git a/src/System.IO.Compression.ZipFile/tests/ZipFileConvenienceMethods.cs b/src/System.IO.Compression.ZipFile/tests/ZipFileConvenienceMethods.cs
index 69c822e3fc7e..3a0255d03862 100644
--- a/src/System.IO.Compression.ZipFile/tests/ZipFileConvenienceMethods.cs
+++ b/src/System.IO.Compression.ZipFile/tests/ZipFileConvenienceMethods.cs
@@ -186,6 +186,23 @@ public void ExtractToDirectoryExtension_Unicode()
             }
         }
 
+        [Theory]
+        [InlineData("../Foo")]
+        [InlineData("../Barbell")]
+        [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Second case fails.")]
+        public void ExtractOutOfRoot(string entryName)
+        {
+            string archivePath = GetTestFilePath();
+            using (FileStream stream = new FileStream(archivePath, FileMode.Create))
+            using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true))
+            {
+                ZipArchiveEntry entry = archive.CreateEntry(entryName);
+            }
+
+            DirectoryInfo destination = Directory.CreateDirectory(Path.Combine(GetTestFilePath(), "Bar"));
+            Assert.Throws<IOException>(() => ZipFile.ExtractToDirectory(archivePath, destination.FullName));
+        }
+
         [Fact]
         public void CreatedEmptyDirectoriesRoundtrip()
         {