Permalink
Browse files

Merge PR #316: Throw exception when attempting to read a zero code le…

…ngth symbol

* Add test for zip file containing 0 code length entries
* Modify GetSymbol to throw on 0 code length symbols
  • Loading branch information...
piksel committed Feb 6, 2019
1 parent fe9e0d8 commit 25ee6440f444aa326ee8f0b98e6223296f35fa6d
@@ -183,13 +183,18 @@ public int GetSymbol(StreamManipulator input)
int lookahead, symbol;
if ((lookahead = input.PeekBits(9)) >= 0)
{
if ((symbol = tree[lookahead]) >= 0)
symbol = tree[lookahead];
int bitlen = symbol & 15;

if (symbol >= 0)
{
input.DropBits(symbol & 15);
if(bitlen == 0){
throw new SharpZipBaseException("Encountered invalid codelength 0");
}
input.DropBits(bitlen);
return symbol >> 4;
}
int subtree = -(symbol >> 4);
int bitlen = symbol & 15;
if ((lookahead = input.PeekBits(bitlen)) >= 0)
{
symbol = tree[subtree | (lookahead >> 9)];
@@ -0,0 +1,20 @@
using System;
using System.Threading;
using System.Reflection;

public class ThreadEx
{
public static void Abort(Thread thread)
{
MethodInfo abort = null;
foreach(MethodInfo m in thread.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
{
if (m.Name.Equals("AbortInternal") && m.GetParameters().Length == 0) abort = m;
}
if (abort == null)
{
throw new Exception("Failed to get Thread.Abort method");
}
abort.Invoke(thread, new object[0]);
}
}
@@ -0,0 +1,57 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using NUnit.Framework;

namespace ICSharpCode.SharpZipLib.Tests.Zip
{
public class ZipCorruptionHandling
{

const string TestFileZeroCodeLength = "UEsDBBQA+AAIANwyZ0U5T8HwjQAAAL8AAAAIABUAbGltZXJpY2t" +
"VVAkAAzBXXFR6LmBUVXgEAPQB9AEFjTEOwjAQBHu/YkVDg3gHoUaivjgHtmKfI5+D5d9zbndHM6/AldFJQTIJ" +
"PrVkPOkgce9QlJFi5hr9rhD+cUUvZ9qgnuRuBAtId97Qw0AL1Kbw5h6MykeKdlyWdlWs7OlUdgsodRqKVo0v8" +
"JWyGWZ6mLpuiii2t2Bl0mZ54QksOIpqXNPATF/eH1BLAQIXAxQAAgAIANxQZ0U5T8HwjQAAAL8AAAAIAA0AAA" +
"AAAAEAAACggQAAAABsaW1lcgEAQwAAAMgAAAAAAA==";

[Test]
[Category("Zip")]
public void ZeroCodeLengthZipFile()
{
Assert.Throws<SharpZipBaseException>(() => {
Exception threadException = null;
var testThread = new Thread(() => {
try {
var fileBytes = Convert.FromBase64String(TestFileZeroCodeLength);
using (var ms = new MemoryStream(fileBytes))
using (var zip = new ZipInputStream(ms))
{
while (zip.GetNextEntry() != null) { }
}
}
catch (Exception x) {
threadException = x;
}
});

testThread.Start();

if(!testThread.Join(5000)){
// Aborting threads is deprecated in .NET Core, but if we don't do this,
// the poor CI will hang for 2 hours upon running this test
ThreadEx.Abort(testThread);
throw new TimeoutException("Timed out waiting for GetNextEntry() to return");
}
else if(threadException != null){
throw threadException;
}
});
}

}

}

0 comments on commit 25ee644

Please sign in to comment.