galeb

Једноставна статичка дистрибуција заснована на musl-у
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

0016-dlang-update-zlib-binding.patch (13412B)


      1 From b2e1bf216169f470ced86f1f3e95c89debf606cd Mon Sep 17 00:00:00 2001
      2 From: Ariadne Conill <ariadne@dereferenced.org>
      3 Date: Fri, 21 Aug 2020 06:57:51 +0000
      4 Subject: [PATCH] dlang: update zlib binding
      5 
      6 ---
      7  libphobos/src/std/zlib.d | 266 ++++++++++++++++++++++++++++-----------
      8  1 file changed, 196 insertions(+), 70 deletions(-)
      9 
     10 diff --git a/libphobos/src/std/zlib.d b/libphobos/src/std/zlib.d
     11 index e6cce240fd5..bd2fe37ebec 100644
     12 --- a/libphobos/src/std/zlib.d
     13 +++ b/libphobos/src/std/zlib.d
     14 @@ -1,7 +1,7 @@
     15  // Written in the D programming language.
     16  
     17  /**
     18 - * Compress/decompress data using the $(HTTP www._zlib.net, _zlib library).
     19 + * Compress/decompress data using the $(HTTP www.zlib.net, zlib library).
     20   *
     21   * Examples:
     22   *
     23 @@ -43,12 +43,12 @@
     24   * References:
     25   *  $(HTTP en.wikipedia.org/wiki/Zlib, Wikipedia)
     26   *
     27 - * Copyright: Copyright Digital Mars 2000 - 2011.
     28 + * Copyright: Copyright The D Language Foundation 2000 - 2011.
     29   * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
     30   * Authors:   $(HTTP digitalmars.com, Walter Bright)
     31 - * Source:    $(PHOBOSSRC std/_zlib.d)
     32 + * Source:    $(PHOBOSSRC std/zlib.d)
     33   */
     34 -/*          Copyright Digital Mars 2000 - 2011.
     35 +/*          Copyright The D Language Foundation 2000 - 2011.
     36   * Distributed under the Boost Software License, Version 1.0.
     37   *    (See accompanying file LICENSE_1_0.txt or copy at
     38   *          http://www.boost.org/LICENSE_1_0.txt)
     39 @@ -75,9 +75,9 @@ enum
     40  
     41  class ZlibException : Exception
     42  {
     43 -    this(int errnum)
     44 -    {   string msg;
     45 -
     46 +    private static string getmsg(int errnum) nothrow @nogc pure @safe
     47 +    {
     48 +        string msg;
     49          switch (errnum)
     50          {
     51              case Z_STREAM_END:      msg = "stream end"; break;
     52 @@ -90,7 +90,12 @@ class ZlibException : Exception
     53              case Z_VERSION_ERROR:   msg = "version error"; break;
     54              default:                msg = "unknown error";  break;
     55          }
     56 -        super(msg);
     57 +        return msg;
     58 +    }
     59 +
     60 +    this(int errnum)
     61 +    {
     62 +        super(getmsg(errnum));
     63      }
     64  }
     65  
     66 @@ -104,7 +109,7 @@ class ZlibException : Exception
     67   *     buf = buffer containing input data
     68   *
     69   * Returns:
     70 - *     A $(D uint) checksum for the provided input data and starting checksum
     71 + *     A `uint` checksum for the provided input data and starting checksum
     72   *
     73   * See_Also:
     74   *     $(LINK http://en.wikipedia.org/wiki/Adler-32)
     75 @@ -147,7 +152,7 @@ uint adler32(uint adler, const(void)[] buf)
     76   *     buf = buffer containing input data
     77   *
     78   * Returns:
     79 - *     A $(D uint) checksum for the provided input data and starting checksum
     80 + *     A `uint` checksum for the provided input data and starting checksum
     81   *
     82   * See_Also:
     83   *     $(LINK http://en.wikipedia.org/wiki/Cyclic_redundancy_check)
     84 @@ -191,13 +196,14 @@ uint crc32(uint crc, const(void)[] buf)
     85  ubyte[] compress(const(void)[] srcbuf, int level)
     86  in
     87  {
     88 -    assert(-1 <= level && level <= 9);
     89 +    assert(-1 <= level && level <= 9, "Compression level needs to be within [-1, 9].");
     90  }
     91 -body
     92 +do
     93  {
     94      import core.memory : GC;
     95 +    import std.array : uninitializedArray;
     96      auto destlen = srcbuf.length + ((srcbuf.length + 1023) / 1024) + 12;
     97 -    auto destbuf = new ubyte[destlen];
     98 +    auto destbuf = uninitializedArray!(ubyte[])(destlen);
     99      auto err = etc.c.zlib.compress2(destbuf.ptr, &destlen, cast(ubyte *) srcbuf.ptr, srcbuf.length, level);
    100      if (err)
    101      {
    102 @@ -276,7 +282,7 @@ void[] uncompress(const(void)[] srcbuf, size_t destlen = 0u, int winbits = 15)
    103                  throw new ZlibException(err);
    104          }
    105      }
    106 -    assert(0);
    107 +    assert(0, "Unreachable code");
    108  }
    109  
    110  @system unittest
    111 @@ -370,9 +376,9 @@ class Compress
    112      this(int level, HeaderFormat header = HeaderFormat.deflate)
    113      in
    114      {
    115 -        assert(1 <= level && level <= 9);
    116 +        assert(1 <= level && level <= 9, "Legal compression level are in [1, 9].");
    117      }
    118 -    body
    119 +    do
    120      {
    121          this.level = level;
    122          this.gzip = header == HeaderFormat.gzip;
    123 @@ -406,6 +412,7 @@ class Compress
    124      const(void)[] compress(const(void)[] buf)
    125      {
    126          import core.memory : GC;
    127 +        import std.array : uninitializedArray;
    128          int err;
    129          ubyte[] destbuf;
    130  
    131 @@ -420,7 +427,7 @@ class Compress
    132              inited = 1;
    133          }
    134  
    135 -        destbuf = new ubyte[zs.avail_in + buf.length];
    136 +        destbuf = uninitializedArray!(ubyte[])(zs.avail_in + buf.length);
    137          zs.next_out = destbuf.ptr;
    138          zs.avail_out = to!uint(destbuf.length);
    139  
    140 @@ -461,9 +468,10 @@ class Compress
    141      void[] flush(int mode = Z_FINISH)
    142      in
    143      {
    144 -        assert(mode == Z_FINISH || mode == Z_SYNC_FLUSH || mode == Z_FULL_FLUSH);
    145 +        assert(mode == Z_FINISH || mode == Z_SYNC_FLUSH || mode == Z_FULL_FLUSH,
    146 +                "Mode must be either Z_FINISH, Z_SYNC_FLUSH or Z_FULL_FLUSH.");
    147      }
    148 -    body
    149 +    do
    150      {
    151          import core.memory : GC;
    152          ubyte[] destbuf;
    153 @@ -523,6 +531,7 @@ class UnCompress
    154      z_stream zs;
    155      int inited;
    156      int done;
    157 +    bool inputEnded;
    158      size_t destbufsize;
    159  
    160      HeaderFormat format;
    161 @@ -571,16 +580,16 @@ class UnCompress
    162      const(void)[] uncompress(const(void)[] buf)
    163      in
    164      {
    165 -        assert(!done);
    166 +        assert(!done, "Buffer has been flushed.");
    167      }
    168 -    body
    169 +    do
    170      {
    171 +        if (inputEnded || !buf.length)
    172 +            return null;
    173 +
    174          import core.memory : GC;
    175 +        import std.array : uninitializedArray;
    176          int err;
    177 -        ubyte[] destbuf;
    178 -
    179 -        if (buf.length == 0)
    180 -            return null;
    181  
    182          if (!inited)
    183          {
    184 @@ -598,26 +607,152 @@ class UnCompress
    185  
    186          if (!destbufsize)
    187              destbufsize = to!uint(buf.length) * 2;
    188 -        destbuf = new ubyte[zs.avail_in * 2 + destbufsize];
    189 -        zs.next_out = destbuf.ptr;
    190 -        zs.avail_out = to!uint(destbuf.length);
    191 -
    192 -        if (zs.avail_in)
    193 -            buf = zs.next_in[0 .. zs.avail_in] ~ cast(ubyte[]) buf;
    194 +        auto destbuf = uninitializedArray!(ubyte[])(destbufsize);
    195 +        size_t destFill;
    196  
    197          zs.next_in = cast(ubyte*) buf.ptr;
    198          zs.avail_in = to!uint(buf.length);
    199  
    200 -        err = inflate(&zs, Z_NO_FLUSH);
    201 -        if (err != Z_STREAM_END && err != Z_OK)
    202 +        while (true)
    203          {
    204 -            GC.free(destbuf.ptr);
    205 -            error(err);
    206 +            auto oldAvailIn = zs.avail_in;
    207 +
    208 +            zs.next_out = destbuf[destFill .. $].ptr;
    209 +            zs.avail_out = to!uint(destbuf.length - destFill);
    210 +
    211 +            err = inflate(&zs, Z_NO_FLUSH);
    212 +            if (err == Z_STREAM_END)
    213 +            {
    214 +                inputEnded = true;
    215 +                break;
    216 +            }
    217 +            else if (err != Z_OK)
    218 +            {
    219 +                GC.free(destbuf.ptr);
    220 +                error(err);
    221 +            }
    222 +            else if (!zs.avail_in)
    223 +                break;
    224 +
    225 +            /*
    226 +                According to the zlib manual inflate() stops when either there's
    227 +                no more data to uncompress or the output buffer is full
    228 +                So at this point, the output buffer is too full
    229 +            */
    230 +
    231 +            destFill = destbuf.length;
    232 +
    233 +            if (destbuf.capacity)
    234 +            {
    235 +                if (destbuf.length < destbuf.capacity)
    236 +                    destbuf.length = destbuf.capacity;
    237 +                else
    238 +                {
    239 +                    auto newLength = GC.extend(destbuf.ptr, destbufsize, destbufsize);
    240 +
    241 +                    if (newLength && destbuf.length < destbuf.capacity)
    242 +                        destbuf.length = destbuf.capacity;
    243 +                    else
    244 +                        destbuf.length += destbufsize;
    245 +                }
    246 +            }
    247 +            else
    248 +                destbuf.length += destbufsize;
    249          }
    250 +
    251          destbuf.length = destbuf.length - zs.avail_out;
    252          return destbuf;
    253      }
    254  
    255 +    // Test for issues 3191 and 9505
    256 +    @system unittest
    257 +    {
    258 +        import std.algorithm.comparison;
    259 +        import std.array;
    260 +        import std.file;
    261 +        import std.zlib;
    262 +
    263 +        // Data that can be easily compressed
    264 +        ubyte[1024] originalData;
    265 +
    266 +        // This should yield a compression ratio of at least 1/2
    267 +        auto compressedData = compress(originalData, 9);
    268 +        assert(compressedData.length < originalData.length / 2,
    269 +                "The compression ratio is too low to accurately test this situation");
    270 +
    271 +        auto chunkSize = compressedData.length / 4;
    272 +        assert(chunkSize < compressedData.length,
    273 +                "The length of the compressed data is too small to accurately test this situation");
    274 +
    275 +        auto decompressor = new UnCompress();
    276 +        ubyte[originalData.length] uncompressedData;
    277 +        ubyte[] reusedBuf;
    278 +        int progress;
    279 +
    280 +        reusedBuf.length = chunkSize;
    281 +
    282 +        for (int i = 0; i < compressedData.length; i += chunkSize)
    283 +        {
    284 +            auto len = min(chunkSize, compressedData.length - i);
    285 +            // simulate reading from a stream in small chunks
    286 +            reusedBuf[0 .. len] = compressedData[i .. i + len];
    287 +
    288 +            // decompress using same input buffer
    289 +            auto chunk = decompressor.uncompress(reusedBuf);
    290 +            assert(progress + chunk.length <= originalData.length,
    291 +                    "The uncompressed result is bigger than the original data");
    292 +
    293 +            uncompressedData[progress .. progress + chunk.length] = cast(const ubyte[]) chunk[];
    294 +            progress += chunk.length;
    295 +        }
    296 +
    297 +        auto chunk = decompressor.flush();
    298 +        assert(progress + chunk.length <= originalData.length,
    299 +                "The uncompressed result is bigger than the original data");
    300 +
    301 +        uncompressedData[progress .. progress + chunk.length] = cast(const ubyte[]) chunk[];
    302 +        progress += chunk.length;
    303 +
    304 +        assert(progress == originalData.length,
    305 +                "The uncompressed and the original data sizes differ");
    306 +        assert(originalData[] == uncompressedData[],
    307 +                "The uncompressed and the original data differ");
    308 +    }
    309 +
    310 +    @system unittest
    311 +    {
    312 +        ubyte[1024] invalidData;
    313 +        auto decompressor = new UnCompress();
    314 +
    315 +        try
    316 +        {
    317 +            auto uncompressedData = decompressor.uncompress(invalidData);
    318 +        }
    319 +        catch (ZlibException e)
    320 +        {
    321 +            assert(e.msg == "data error");
    322 +            return;
    323 +        }
    324 +
    325 +        assert(false, "Corrupted data didn't result in an error");
    326 +    }
    327 +
    328 +    @system unittest
    329 +    {
    330 +        ubyte[2014] originalData = void;
    331 +        auto compressedData = compress(originalData, 9);
    332 +
    333 +        auto decompressor = new UnCompress();
    334 +        auto uncompressedData = decompressor.uncompress(compressedData ~ cast(ubyte[]) "whatever");
    335 +
    336 +        assert(originalData.length == uncompressedData.length,
    337 +                "The uncompressed and the original data sizes differ");
    338 +        assert(originalData[] == uncompressedData[],
    339 +                "The uncompressed and the original data differ");
    340 +        assert(!decompressor.uncompress("whatever").length,
    341 +                "Compression continued after the end");
    342 +    }
    343 +
    344      /**
    345       * Decompress and return any remaining data.
    346       * The returned data should be appended to that returned by uncompress().
    347 @@ -626,49 +761,40 @@ class UnCompress
    348      void[] flush()
    349      in
    350      {
    351 -        assert(!done);
    352 +        assert(!done, "Buffer has been flushed before.");
    353      }
    354      out
    355      {
    356 -        assert(done);
    357 +        assert(done, "Flushing failed.");
    358      }
    359 -    body
    360 +    do
    361      {
    362 -        import core.memory : GC;
    363 -        ubyte[] extra;
    364 -        ubyte[] destbuf;
    365 -        int err;
    366 -
    367          done = 1;
    368 -        if (!inited)
    369 -            return null;
    370 +        return null;
    371 +    }
    372  
    373 -      L1:
    374 -        destbuf = new ubyte[zs.avail_in * 2 + 100];
    375 -        zs.next_out = destbuf.ptr;
    376 -        zs.avail_out = to!uint(destbuf.length);
    377 +    /// Returns true if all input data has been decompressed and no further data
    378 +    /// can be decompressed (inflate() returned Z_STREAM_END)
    379 +    @property bool empty() const
    380 +    {
    381 +        return inputEnded;
    382 +    }
    383  
    384 -        err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
    385 -        if (err == Z_OK && zs.avail_out == 0)
    386 -        {
    387 -            extra ~= destbuf;
    388 -            goto L1;
    389 -        }
    390 -        if (err != Z_STREAM_END)
    391 -        {
    392 -            GC.free(destbuf.ptr);
    393 -            if (err == Z_OK)
    394 -                err = Z_BUF_ERROR;
    395 -            error(err);
    396 -        }
    397 -        destbuf = destbuf.ptr[0 .. zs.next_out - destbuf.ptr];
    398 -        err = etc.c.zlib.inflateEnd(&zs);
    399 -        inited = 0;
    400 -        if (err)
    401 -            error(err);
    402 -        if (extra.length)
    403 -            destbuf = extra ~ destbuf;
    404 -        return destbuf;
    405 +    ///
    406 +    @system unittest
    407 +    {
    408 +        // some random data
    409 +        ubyte[1024] originalData = void;
    410 +
    411 +        // append garbage data (or don't, this works in both cases)
    412 +        auto compressedData = cast(ubyte[]) compress(originalData) ~ cast(ubyte[]) "whatever";
    413 +
    414 +        auto decompressor = new UnCompress();
    415 +        auto uncompressedData = decompressor.uncompress(compressedData);
    416 +
    417 +        assert(uncompressedData[] == originalData[],
    418 +                "The uncompressed and the original data differ");
    419 +        assert(decompressor.empty, "The UnCompressor reports not being done");
    420      }
    421  }
    422  
    423 -- 
    424 2.31.1
    425