deflatePending not available in zlib on OpenBSD (undefined symbol)

Anatoli me at anatoli.ws
Tue Jun 2 19:34:16 EDT 2020


Looks good to me and compiles correctly on OpenBSD.

Could it be included in the next 3.2 release (3.2.2)?


On 2/6/20 19:31, Ken Murchison wrote:
> Yes, you're correct.  We have a comment in prot.c that quotes the same
> passage ion the docs.
> 
> I think this might do the trick:
> 
> 
> diff --git a/imap/httpd.c b/imap/httpd.c
> index fc430d935..b5014b97e 100644
> --- a/imap/httpd.c
> +++ b/imap/httpd.c
> @@ -149,24 +149,12 @@ HIDDEN int zlib_compress(struct transaction_t
> *txn, unsigned flags,
>      zstrm->next_in = (Bytef *) buf;
>      zstrm->avail_in = len;
> 
> -    buf_ensure(&txn->zbuf, deflateBound(zstrm, zstrm->avail_in));
>      buf_reset(&txn->zbuf);
> 
>      do {
>          int zr;
> 
> -        if (!zstrm->avail_out) {
> -            unsigned pending;
> -
> -            zr = deflatePending(zstrm, &pending, Z_NULL);
> -            if (zr != Z_OK) {
> -                /* something went wrong */
> -                syslog(LOG_ERR, "zlib deflate error: %d %s", zr,
> zstrm->msg);
> -                return -1;
> -            }
> -
> -            buf_ensure(&txn->zbuf, pending);
> -        }
> +        buf_ensure(&txn->zbuf, deflateBound(zstrm, len));
> 
>          zstrm->next_out = (Bytef *) txn->zbuf.s + txn->zbuf.len;
>          zstrm->avail_out = txn->zbuf.alloc - txn->zbuf.len;
> 
> 
> On 6/2/20 6:19 PM, Anatoli wrote:
>> Hi Ken,
>>
>> According to the docs [1]: If deflate returns Z_OK and with zero
>> avail_out, it must be called again after making room in the buffer
>> because there might be more output pending.
>>
>> On the other hand it says: Z_FINISH can be used in the first deflate
>> call after deflateInit if all the compression is to be done in a single
>> step. In order to complete in one call, avail_out must be at least the
>> value returned by deflateBound. Then deflate is guaranteed to return
>> Z_STREAM_END.
>>
>> But: Note that it is possible for the compressed size to be larger than
>> the value returned by deflateBound() if flush options other than
>> Z_FINISH or Z_NO_FLUSH are used.
>>
>>
>> At the beginning of zlib_compress() there's code that decides with which
>> flush option to call deflate().
>>
>> /* Only flush for static content or on last (zero-length) chunk */
>>
>> If it's possible to make flush to be always Z_FINISH, then I guess the
>> entire
>>
>> do { ... } while (!zstrm->avail_out);
>>
>> loop could be simplified to just:
>>
>> zstrm->next_out = (Bytef *) txn->zbuf.s + txn->zbuf.len;
>> zstrm->avail_out = txn->zbuf.alloc - txn->zbuf.len;
>>
>> zr = deflate(zstrm, flush);
>> if (zr != Z_STREAM_END) {
>>     /* something went wrong */
>>     syslog(LOG_ERR, "zlib deflate error: %d %s", zr, zstrm->msg);
>>     return -1;
>> }
>>
>>
>> I changed the "if (zr)" condition as the only good value would be
>> Z_STREAM_END.
>>
>> But if the flush option can't be always Z_FINISH, then I believe the
>> loop should be kept with the checks for !zstrm->avail_out as it's
>> possible that there would be not enough buffer for deflate() to complete
>> in one call.
>>
>> Regards,
>> Anatoli
>>
>> [1] https://www.zlib.net/manual.html
>>
>>
>>
>> On 2/6/20 17:36, Ken Murchison wrote:
>>> Hi Anatoli,
>>>
>>> Thanks for the report.  I'm not sure that we even need the
>>> deflatePending() call, since we use deflateBound() to create an
>>> appropriately-sized buffer to hold the entire compressed response body.
>>> Let me do some testing.
>>>
>>>
>>> On 6/2/20 3:48 AM, Anatoli wrote:
>>>> Cyrus developers,
>>>>
>>>> Is it possible to somehow rework the code in imap/httpd.c lines 158-169
>>>> in order to NOT use deflatePending as this func is not available on
>>>> OpenBSD? The zlib version there is 1.2.3 and deflatePending appeared in
>>>> 1.2.5 so the code doesn't compile with --enable-http (undefined symbol:
>>>> deflatePending). The packaged version disables http for now.
>>>>
>>>> Is it safe to reduce these lines:
>>>>
>>>>    158         if (!zstrm->avail_out) {
>>>>    159             unsigned pending;
>>>>    160
>>>>    161             zr = deflatePending(zstrm, &pending, Z_NULL);
>>>>    162             if (zr != Z_OK) {
>>>>    163                 /* something went wrong */
>>>>    164                 syslog(LOG_ERR, "zlib deflate error: %d %s", zr,
>>>> zstrm->msg);
>>>>    165                 return -1;
>>>>    166             }
>>>>    167
>>>>    168             buf_ensure(&txn->zbuf, pending);
>>>>    169         }
>>>>
>>>>
>>>> to something like:
>>>>
>>>>    158         if (!zstrm->avail_out) {
>>>>    159             buf_ensure(&txn->zbuf, 256 * 1024);
>>>>    160         }
>>>>
>>>> If I understand it correctly, deflatePending in this case is only used
>>>> to get the needed buffer size and we could replace it with a hardcoded
>>>> buffer size (like in my example of 256K).
>>>>
>>>>
>>>> Thanks,
>>>> Anatoli
> 


More information about the Cyrus-devel mailing list