Skip to content

Commit 25ee644

Browse files
authored
Merge PR #316: Throw exception when attempting to read a zero code length symbol
* Add test for zip file containing 0 code length entries * Modify GetSymbol to throw on 0 code length symbols
1 parent fe9e0d8 commit 25ee644

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

src/ICSharpCode.SharpZipLib/Zip/Compression/InflaterHuffmanTree.cs

+8-3
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,18 @@ public int GetSymbol(StreamManipulator input)
183183
int lookahead, symbol;
184184
if ((lookahead = input.PeekBits(9)) >= 0)
185185
{
186-
if ((symbol = tree[lookahead]) >= 0)
186+
symbol = tree[lookahead];
187+
int bitlen = symbol & 15;
188+
189+
if (symbol >= 0)
187190
{
188-
input.DropBits(symbol & 15);
191+
if(bitlen == 0){
192+
throw new SharpZipBaseException("Encountered invalid codelength 0");
193+
}
194+
input.DropBits(bitlen);
189195
return symbol >> 4;
190196
}
191197
int subtree = -(symbol >> 4);
192-
int bitlen = symbol & 15;
193198
if ((lookahead = input.PeekBits(bitlen)) >= 0)
194199
{
195200
symbol = tree[subtree | (lookahead >> 9)];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Threading;
3+
using System.Reflection;
4+
5+
public class ThreadEx
6+
{
7+
public static void Abort(Thread thread)
8+
{
9+
MethodInfo abort = null;
10+
foreach(MethodInfo m in thread.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
11+
{
12+
if (m.Name.Equals("AbortInternal") && m.GetParameters().Length == 0) abort = m;
13+
}
14+
if (abort == null)
15+
{
16+
throw new Exception("Failed to get Thread.Abort method");
17+
}
18+
abort.Invoke(thread, new object[0]);
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.IO;
3+
using System.Runtime.InteropServices;
4+
using System.Text;
5+
using System.Threading;
6+
using ICSharpCode.SharpZipLib;
7+
using ICSharpCode.SharpZipLib.Zip;
8+
using NUnit.Framework;
9+
10+
namespace ICSharpCode.SharpZipLib.Tests.Zip
11+
{
12+
public class ZipCorruptionHandling
13+
{
14+
15+
const string TestFileZeroCodeLength = "UEsDBBQA+AAIANwyZ0U5T8HwjQAAAL8AAAAIABUAbGltZXJpY2t" +
16+
"VVAkAAzBXXFR6LmBUVXgEAPQB9AEFjTEOwjAQBHu/YkVDg3gHoUaivjgHtmKfI5+D5d9zbndHM6/AldFJQTIJ" +
17+
"PrVkPOkgce9QlJFi5hr9rhD+cUUvZ9qgnuRuBAtId97Qw0AL1Kbw5h6MykeKdlyWdlWs7OlUdgsodRqKVo0v8" +
18+
"JWyGWZ6mLpuiii2t2Bl0mZ54QksOIpqXNPATF/eH1BLAQIXAxQAAgAIANxQZ0U5T8HwjQAAAL8AAAAIAA0AAA" +
19+
"AAAAEAAACggQAAAABsaW1lcgEAQwAAAMgAAAAAAA==";
20+
21+
[Test]
22+
[Category("Zip")]
23+
public void ZeroCodeLengthZipFile()
24+
{
25+
Assert.Throws<SharpZipBaseException>(() => {
26+
Exception threadException = null;
27+
var testThread = new Thread(() => {
28+
try {
29+
var fileBytes = Convert.FromBase64String(TestFileZeroCodeLength);
30+
using (var ms = new MemoryStream(fileBytes))
31+
using (var zip = new ZipInputStream(ms))
32+
{
33+
while (zip.GetNextEntry() != null) { }
34+
}
35+
}
36+
catch (Exception x) {
37+
threadException = x;
38+
}
39+
});
40+
41+
testThread.Start();
42+
43+
if(!testThread.Join(5000)){
44+
// Aborting threads is deprecated in .NET Core, but if we don't do this,
45+
// the poor CI will hang for 2 hours upon running this test
46+
ThreadEx.Abort(testThread);
47+
throw new TimeoutException("Timed out waiting for GetNextEntry() to return");
48+
}
49+
else if(threadException != null){
50+
throw threadException;
51+
}
52+
});
53+
}
54+
55+
}
56+
57+
}

0 commit comments

Comments
 (0)