Hi,

Please help review the change for #8184306.

issue: https://bugs.openjdk.java.net/browse/JDK-8184306
webrev: http://cr.openjdk.java.net/~sherman/8184306/

Background:

It appears the basic compression functionality of j.u.Deflater is broken when

(1) the deflater's compression level/strategy is changed (to new value) AND
(2) reset()

which is a normal combination/use scenario when the deflater is being cached
and reused.

My reading of the 1.2.11 changes suggests the root cause is that the internal state "deflate_state.high_water" is not being reset correctly/appropriately (to 0?)
in deflateReset/deflateResetKeep/lm_init().

AND the change of one of the conditions in deflate.c/deflateParams(), from
"strm->total_in!=0" to "s->high_water" (in the "Flush last buffer" branch) as showed below, obvious triggers the regression from 1.2.8 to 1.2.11, in the scenario that
the "strategy/levle is changed" AND a followup "reset()" is called (with the
assumption that everything should be reset back to initial state and we start a new compression circle, with the new level and strategy. This is how it works
in 1.2.8 and early releases).

from (1.2.8's)

if ((strategy != s->strategy || func != configuration_table[level].func) &&
    strm->total_in != 0) { <----------------
    /* Flush the last buffer: */
    err = deflate(strm, Z_BLOCK);
    if (err == Z_BUF_ERROR && s->pending == 0)
        err = Z_OK;
}

to (1.2.11's)

if ((strategy != s->strategy || func != configuration_table[level].func) &&
    s->high_water) { <-----------------
    /* Flush the last buffer: */
    int err = deflate(strm, Z_BLOCK);
    if (err == Z_STREAM_ERROR)
        return err;
    if (strm->avail_out == 0)
        return Z_BUF_ERROR;
}

With this change (in 1.2.11), now if there is any compression operation that
leaves the "s->high_water" > 0, even after the "reset()" has been called, the next compression/deflateParam() will always "try to flush the last buffer" with
the old state, which appears to be wrong.

Given the nature of "reset" it appears reasonable to assume the "high_water" should be reset to 0, its initial value as well, inside either deflateResetKeep()
or lm_init().

I have logged an issue at

https://github.com/madler/zlib/issues/275

Jdk9 has been changed to use the system zlib for all platforms except the
windows, this one currently only fails on windows. But I would assume if the
underlying zlib is 1.2.11, the deflater/compression will be broken as well.
Have not verified this yet. Anyone has a zlib 1.2.11 installed and trying jdk9
on it (on a non-Windows system) ?

Instead of backout the 1.2.11 completely and reset back  to 1.2.8, here I'm
proposing to add the suggested one-line change to "fix" this issue for now and waiting for any official fix from zlib. The change seems easy and safe for me.
It does fix the failure we are experiencing now.

Thanks,
Sherman

Reply via email to