diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
index 562480a3c..7bc770d17 100644
--- a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
+++ b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
@@ -1,6 +1,8 @@
using System;
using System.IO;
+using System.Numerics;
using System.Text;
+using ICSharpCode.SharpZipLib.Core;
namespace ICSharpCode.SharpZipLib.Tar
{
@@ -594,13 +596,25 @@ public void ListContents()
///
/// The destination directory into which to extract.
///
- public void ExtractContents(string destinationDirectory)
+ public void ExtractContents(string destinationDirectory)
+ => ExtractContents(destinationDirectory, false);
+
+ ///
+ /// Perform the "extract" command and extract the contents of the archive.
+ ///
+ ///
+ /// The destination directory into which to extract.
+ ///
+ /// Allow parent directory traversal in file paths (e.g. ../file)
+ public void ExtractContents(string destinationDirectory, bool allowParentTraversal)
{
if (isDisposed)
{
throw new ObjectDisposedException("TarArchive");
}
+ var fullDistDir = Path.GetFullPath(destinationDirectory);
+
while (true)
{
TarEntry entry = tarIn.GetNextEntry();
@@ -613,7 +627,7 @@ public void ExtractContents(string destinationDirectory)
if (entry.TarHeader.TypeFlag == TarHeader.LF_LINK || entry.TarHeader.TypeFlag == TarHeader.LF_SYMLINK)
continue;
- ExtractEntry(destinationDirectory, entry);
+ ExtractEntry(fullDistDir, entry, allowParentTraversal);
}
}
@@ -627,7 +641,8 @@ public void ExtractContents(string destinationDirectory)
///
/// The TarEntry returned by tarIn.GetNextEntry().
///
- private void ExtractEntry(string destDir, TarEntry entry)
+ /// Allow parent directory traversal in file paths (e.g. ../file)
+ private void ExtractEntry(string destDir, TarEntry entry, bool allowParentTraversal)
{
OnProgressMessageEvent(entry, null);
@@ -644,6 +659,11 @@ private void ExtractEntry(string destDir, TarEntry entry)
string destFile = Path.Combine(destDir, name);
+ if (!allowParentTraversal && !Path.GetFullPath(destFile).StartsWith(destDir, StringComparison.InvariantCultureIgnoreCase))
+ {
+ throw new InvalidNameException("Parent traversal in paths is not allowed");
+ }
+
if (entry.IsDirectory)
{
EnsureDirectoryExists(destFile);