Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
<data name="UnauthorizedAccess_IODenied_Path" xml:space="preserve">
<value>Access to the path '{0}' is denied.</value>
</data>
<data name="IO_DirectoryNotAllowed" xml:space="preserve">
<value>The specified path '{0}' is a directory, which is not allowed in this operation.</value>
</data>
<data name="ZipUnsupportedFile" xml:space="preserve">
<value>The file type of '{0}' is not supported for zip archiving.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,20 @@ private static FileStream GetFileStreamForOpen(ZipArchiveMode mode, string archi
_ => throw new ArgumentOutOfRangeException(nameof(mode)),
};

return new FileStream(archiveFileName, fileMode, access, fileShare, bufferSize: FileStreamBufferSize, useAsync);
try
{
return new FileStream(archiveFileName, fileMode, access, fileShare, bufferSize: FileStreamBufferSize, useAsync);
}
catch (UnauthorizedAccessException) when (Directory.Exists(archiveFileName))
{
// If we get UnauthorizedAccessException and the path is a directory, provide a clearer error message
throw new UnauthorizedAccessException(SR.Format(SR.IO_DirectoryNotAllowed, archiveFileName));
}
catch (IOException) when (mode == ZipArchiveMode.Create && Directory.Exists(archiveFileName))
{
// If we get IOException in Create mode and the path is a directory, provide a clearer error message
throw new IOException(SR.Format(SR.IO_DirectoryNotAllowed, archiveFileName));
}
}

private static (string, string) GetFullPathsForDoCreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ public async Task ExtractToDirectoryNull(bool async)
await AssertExtensions.ThrowsAsync<ArgumentNullException>("sourceArchiveFileName", () => CallZipFileExtractToDirectory(async, sourceArchiveFileName: null, GetTestFilePath()));
}

[Theory]
[MemberData(nameof(Get_Booleans_Data))]
public async Task ExtractToDirectory_PassDirectoryAsArchiveFile_ThrowsUnauthorizedAccessException(bool async)
{
string directoryPath = GetTestFilePath();
Directory.CreateDirectory(directoryPath);

await Assert.ThrowsAsync<UnauthorizedAccessException>(() =>
CallZipFileExtractToDirectory(async, directoryPath, GetTestFilePath()));
}

[Theory]
[MemberData(nameof(Get_Booleans_Data))]
public async Task ExtractToDirectoryUnicode(bool async)
Expand Down
40 changes: 40 additions & 0 deletions src/libraries/System.IO.Compression.ZipFile/tests/ZipFile.Open.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,46 @@ public Task InvalidConstructors(bool async)
return Assert.ThrowsAsync<ArgumentOutOfRangeException>(() => CallZipFileOpen(async, "bad file", (ZipArchiveMode)(10)));
}

[Fact]
public void Open_PassDirectory_ThrowsUnauthorizedAccessException()
{
string directoryPath = GetTestFilePath();
Directory.CreateDirectory(directoryPath);

Assert.Throws<UnauthorizedAccessException>(() => ZipFile.Open(directoryPath, ZipArchiveMode.Read));
Assert.Throws<UnauthorizedAccessException>(() => ZipFile.OpenRead(directoryPath));
Assert.Throws<UnauthorizedAccessException>(() => ZipFile.Open(directoryPath, ZipArchiveMode.Update));
}

[Fact]
public void Open_PassDirectory_CreateMode_ThrowsIOException()
{
string directoryPath = GetTestFilePath();
Directory.CreateDirectory(directoryPath);

Assert.Throws<IOException>(() => ZipFile.Open(directoryPath, ZipArchiveMode.Create));
}

[Fact]
public async Task OpenAsync_PassDirectory_ThrowsUnauthorizedAccessException()
{
string directoryPath = GetTestFilePath();
Directory.CreateDirectory(directoryPath);

await Assert.ThrowsAsync<UnauthorizedAccessException>(() => ZipFile.OpenAsync(directoryPath, ZipArchiveMode.Read, default));
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => ZipFile.OpenReadAsync(directoryPath, default));
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => ZipFile.OpenAsync(directoryPath, ZipArchiveMode.Update, default));
}

[Fact]
public async Task OpenAsync_PassDirectory_CreateMode_ThrowsIOException()
{
string directoryPath = GetTestFilePath();
Directory.CreateDirectory(directoryPath);

await Assert.ThrowsAsync<IOException>(() => ZipFile.OpenAsync(directoryPath, ZipArchiveMode.Create, default));
}

[Fact]
public void InvalidFiles()
{
Expand Down
Loading