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