|
|
# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../musl/pkg/gcc/0016-dlang-update-zlib-binding.patch # Copyright (C) 2020 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END ---
From 7fc386a2e629e859968da4eb4d0ff4983cb3b76f Mon Sep 17 00:00:00 2001 From: Ariadne Conill <ariadne@dereferenced.org> Date: Fri, 21 Aug 2020 06:57:51 +0000 Subject: [PATCH 16/30] dlang: update zlib binding
---
libphobos/src/std/zlib.d | 266 ++++++++++++++++++++++++++++----------- 1 file changed, 196 insertions(+), 70 deletions(-)
diff --git a/libphobos/src/std/zlib.d b/libphobos/src/std/zlib.d
index e6cce240fd5..bd2fe37ebec 100644
--- a/libphobos/src/std/zlib.d
+++ b/libphobos/src/std/zlib.d
@@ -1,7 +1,7 @@
// Written in the D programming language. /** - * Compress/decompress data using the $(HTTP www._zlib.net, _zlib library).
+ * Compress/decompress data using the $(HTTP www.zlib.net, zlib library).
* * Examples: * @@ -43,12 +43,12 @@
* References: * $(HTTP en.wikipedia.org/wiki/Zlib, Wikipedia) * - * Copyright: Copyright Digital Mars 2000 - 2011.
+ * Copyright: Copyright The D Language Foundation 2000 - 2011.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: $(HTTP digitalmars.com, Walter Bright) - * Source: $(PHOBOSSRC std/_zlib.d)
+ * Source: $(PHOBOSSRC std/zlib.d)
*/ -/* Copyright Digital Mars 2000 - 2011.
+/* Copyright The D Language Foundation 2000 - 2011.
* Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) @@ -75,9 +75,9 @@ enum
class ZlibException : Exception { - this(int errnum)
- { string msg;
-
+ private static string getmsg(int errnum) nothrow @nogc pure @safe
+ {
+ string msg;
switch (errnum) { case Z_STREAM_END: msg = "stream end"; break; @@ -90,7 +90,12 @@ class ZlibException : Exception
case Z_VERSION_ERROR: msg = "version error"; break; default: msg = "unknown error"; break; } - super(msg);
+ return msg;
+ }
+
+ this(int errnum)
+ {
+ super(getmsg(errnum));
} } @@ -104,7 +109,7 @@ class ZlibException : Exception
* buf = buffer containing input data * * Returns: - * A $(D uint) checksum for the provided input data and starting checksum
+ * A `uint` checksum for the provided input data and starting checksum
* * See_Also: * $(LINK http://en.wikipedia.org/wiki/Adler-32) @@ -147,7 +152,7 @@ uint adler32(uint adler, const(void)[] buf)
* buf = buffer containing input data * * Returns: - * A $(D uint) checksum for the provided input data and starting checksum
+ * A `uint` checksum for the provided input data and starting checksum
* * See_Also: * $(LINK http://en.wikipedia.org/wiki/Cyclic_redundancy_check) @@ -191,13 +196,14 @@ uint crc32(uint crc, const(void)[] buf)
ubyte[] compress(const(void)[] srcbuf, int level) in { - assert(-1 <= level && level <= 9);
+ assert(-1 <= level && level <= 9, "Compression level needs to be within [-1, 9].");
} -body
+do
{ import core.memory : GC; + import std.array : uninitializedArray;
auto destlen = srcbuf.length + ((srcbuf.length + 1023) / 1024) + 12; - auto destbuf = new ubyte[destlen];
+ auto destbuf = uninitializedArray!(ubyte[])(destlen);
auto err = etc.c.zlib.compress2(destbuf.ptr, &destlen, cast(ubyte *) srcbuf.ptr, srcbuf.length, level); if (err) { @@ -276,7 +282,7 @@ void[] uncompress(const(void)[] srcbuf, size_t destlen = 0u, int winbits = 15)
throw new ZlibException(err); } } - assert(0);
+ assert(0, "Unreachable code");
} @system unittest @@ -370,9 +376,9 @@ class Compress
this(int level, HeaderFormat header = HeaderFormat.deflate) in { - assert(1 <= level && level <= 9);
+ assert(1 <= level && level <= 9, "Legal compression level are in [1, 9].");
} - body
+ do
{ this.level = level; this.gzip = header == HeaderFormat.gzip; @@ -406,6 +412,7 @@ class Compress
const(void)[] compress(const(void)[] buf) { import core.memory : GC; + import std.array : uninitializedArray;
int err; ubyte[] destbuf; @@ -420,7 +427,7 @@ class Compress
inited = 1; } - destbuf = new ubyte[zs.avail_in + buf.length];
+ destbuf = uninitializedArray!(ubyte[])(zs.avail_in + buf.length);
zs.next_out = destbuf.ptr; zs.avail_out = to!uint(destbuf.length); @@ -461,9 +468,10 @@ class Compress
void[] flush(int mode = Z_FINISH) in { - assert(mode == Z_FINISH || mode == Z_SYNC_FLUSH || mode == Z_FULL_FLUSH);
+ assert(mode == Z_FINISH || mode == Z_SYNC_FLUSH || mode == Z_FULL_FLUSH,
+ "Mode must be either Z_FINISH, Z_SYNC_FLUSH or Z_FULL_FLUSH.");
} - body
+ do
{ import core.memory : GC; ubyte[] destbuf; @@ -523,6 +531,7 @@ class UnCompress
z_stream zs; int inited; int done; + bool inputEnded;
size_t destbufsize; HeaderFormat format; @@ -571,16 +580,16 @@ class UnCompress
const(void)[] uncompress(const(void)[] buf) in { - assert(!done);
+ assert(!done, "Buffer has been flushed.");
} - body
+ do
{ + if (inputEnded || !buf.length)
+ return null;
+
import core.memory : GC; + import std.array : uninitializedArray;
int err; - ubyte[] destbuf;
-
- if (buf.length == 0)
- return null;
if (!inited) { @@ -598,26 +607,152 @@ class UnCompress
if (!destbufsize) destbufsize = to!uint(buf.length) * 2; - destbuf = new ubyte[zs.avail_in * 2 + destbufsize];
- zs.next_out = destbuf.ptr;
- zs.avail_out = to!uint(destbuf.length);
-
- if (zs.avail_in)
- buf = zs.next_in[0 .. zs.avail_in] ~ cast(ubyte[]) buf;
+ auto destbuf = uninitializedArray!(ubyte[])(destbufsize);
+ size_t destFill;
zs.next_in = cast(ubyte*) buf.ptr; zs.avail_in = to!uint(buf.length); - err = inflate(&zs, Z_NO_FLUSH);
- if (err != Z_STREAM_END && err != Z_OK)
+ while (true)
{ - GC.free(destbuf.ptr);
- error(err);
+ auto oldAvailIn = zs.avail_in;
+
+ zs.next_out = destbuf[destFill .. $].ptr;
+ zs.avail_out = to!uint(destbuf.length - destFill);
+
+ err = inflate(&zs, Z_NO_FLUSH);
+ if (err == Z_STREAM_END)
+ {
+ inputEnded = true;
+ break;
+ }
+ else if (err != Z_OK)
+ {
+ GC.free(destbuf.ptr);
+ error(err);
+ }
+ else if (!zs.avail_in)
+ break;
+
+ /*
+ According to the zlib manual inflate() stops when either there's
+ no more data to uncompress or the output buffer is full
+ So at this point, the output buffer is too full
+ */
+
+ destFill = destbuf.length;
+
+ if (destbuf.capacity)
+ {
+ if (destbuf.length < destbuf.capacity)
+ destbuf.length = destbuf.capacity;
+ else
+ {
+ auto newLength = GC.extend(destbuf.ptr, destbufsize, destbufsize);
+
+ if (newLength && destbuf.length < destbuf.capacity)
+ destbuf.length = destbuf.capacity;
+ else
+ destbuf.length += destbufsize;
+ }
+ }
+ else
+ destbuf.length += destbufsize;
} +
destbuf.length = destbuf.length - zs.avail_out; return destbuf; } + // Test for issues 3191 and 9505
+ @system unittest
+ {
+ import std.algorithm.comparison;
+ import std.array;
+ import std.file;
+ import std.zlib;
+
+ // Data that can be easily compressed
+ ubyte[1024] originalData;
+
+ // This should yield a compression ratio of at least 1/2
+ auto compressedData = compress(originalData, 9);
+ assert(compressedData.length < originalData.length / 2,
+ "The compression ratio is too low to accurately test this situation");
+
+ auto chunkSize = compressedData.length / 4;
+ assert(chunkSize < compressedData.length,
+ "The length of the compressed data is too small to accurately test this situation");
+
+ auto decompressor = new UnCompress();
+ ubyte[originalData.length] uncompressedData;
+ ubyte[] reusedBuf;
+ int progress;
+
+ reusedBuf.length = chunkSize;
+
+ for (int i = 0; i < compressedData.length; i += chunkSize)
+ {
+ auto len = min(chunkSize, compressedData.length - i);
+ // simulate reading from a stream in small chunks
+ reusedBuf[0 .. len] = compressedData[i .. i + len];
+
+ // decompress using same input buffer
+ auto chunk = decompressor.uncompress(reusedBuf);
+ assert(progress + chunk.length <= originalData.length,
+ "The uncompressed result is bigger than the original data");
+
+ uncompressedData[progress .. progress + chunk.length] = cast(const ubyte[]) chunk[];
+ progress += chunk.length;
+ }
+
+ auto chunk = decompressor.flush();
+ assert(progress + chunk.length <= originalData.length,
+ "The uncompressed result is bigger than the original data");
+
+ uncompressedData[progress .. progress + chunk.length] = cast(const ubyte[]) chunk[];
+ progress += chunk.length;
+
+ assert(progress == originalData.length,
+ "The uncompressed and the original data sizes differ");
+ assert(originalData[] == uncompressedData[],
+ "The uncompressed and the original data differ");
+ }
+
+ @system unittest
+ {
+ ubyte[1024] invalidData;
+ auto decompressor = new UnCompress();
+
+ try
+ {
+ auto uncompressedData = decompressor.uncompress(invalidData);
+ }
+ catch (ZlibException e)
+ {
+ assert(e.msg == "data error");
+ return;
+ }
+
+ assert(false, "Corrupted data didn't result in an error");
+ }
+
+ @system unittest
+ {
+ ubyte[2014] originalData = void;
+ auto compressedData = compress(originalData, 9);
+
+ auto decompressor = new UnCompress();
+ auto uncompressedData = decompressor.uncompress(compressedData ~ cast(ubyte[]) "whatever");
+
+ assert(originalData.length == uncompressedData.length,
+ "The uncompressed and the original data sizes differ");
+ assert(originalData[] == uncompressedData[],
+ "The uncompressed and the original data differ");
+ assert(!decompressor.uncompress("whatever").length,
+ "Compression continued after the end");
+ }
+
/** * Decompress and return any remaining data. * The returned data should be appended to that returned by uncompress(). @@ -626,49 +761,40 @@ class UnCompress
void[] flush() in { - assert(!done);
+ assert(!done, "Buffer has been flushed before.");
} out { - assert(done);
+ assert(done, "Flushing failed.");
} - body
+ do
{ - import core.memory : GC;
- ubyte[] extra;
- ubyte[] destbuf;
- int err;
-
done = 1; - if (!inited)
- return null;
+ return null;
+ }
- L1:
- destbuf = new ubyte[zs.avail_in * 2 + 100];
- zs.next_out = destbuf.ptr;
- zs.avail_out = to!uint(destbuf.length);
+ /// Returns true if all input data has been decompressed and no further data
+ /// can be decompressed (inflate() returned Z_STREAM_END)
+ @property bool empty() const
+ {
+ return inputEnded;
+ }
- err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
- if (err == Z_OK && zs.avail_out == 0)
- {
- extra ~= destbuf;
- goto L1;
- }
- if (err != Z_STREAM_END)
- {
- GC.free(destbuf.ptr);
- if (err == Z_OK)
- err = Z_BUF_ERROR;
- error(err);
- }
- destbuf = destbuf.ptr[0 .. zs.next_out - destbuf.ptr];
- err = etc.c.zlib.inflateEnd(&zs);
- inited = 0;
- if (err)
- error(err);
- if (extra.length)
- destbuf = extra ~ destbuf;
- return destbuf;
+ ///
+ @system unittest
+ {
+ // some random data
+ ubyte[1024] originalData = void;
+
+ // append garbage data (or don't, this works in both cases)
+ auto compressedData = cast(ubyte[]) compress(originalData) ~ cast(ubyte[]) "whatever";
+
+ auto decompressor = new UnCompress();
+ auto uncompressedData = decompressor.uncompress(compressedData);
+
+ assert(uncompressedData[] == originalData[],
+ "The uncompressed and the original data differ");
+ assert(decompressor.empty, "The UnCompressor reports not being done");
} } --
2.27.0
|