aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/nifs/common/zlib_nif.c25
-rw-r--r--erts/preloaded/ebin/zlib.beambin19784 -> 19744 bytes
-rw-r--r--erts/preloaded/src/zlib.erl13
3 files changed, 27 insertions, 11 deletions
diff --git a/erts/emulator/nifs/common/zlib_nif.c b/erts/emulator/nifs/common/zlib_nif.c
index fa29b4fb71..9565a5a059 100644
--- a/erts/emulator/nifs/common/zlib_nif.c
+++ b/erts/emulator/nifs/common/zlib_nif.c
@@ -717,7 +717,9 @@ static ERL_NIF_TERM zlib_deflateEnd(ErlNifEnv *env, int argc, const ERL_NIF_TERM
static ERL_NIF_TERM zlib_deflateParams(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
zlib_data_t *d;
+
int res, level, strategy;
+ Bytef dummy_buffer;
if(argc != 3 || !get_zlib_data(env, argv[0], &d)
|| !enif_get_int(env, argv[1], &level)
@@ -729,12 +731,27 @@ static ERL_NIF_TERM zlib_deflateParams(ErlNifEnv *env, int argc, const ERL_NIF_T
return enif_raise_exception(env, am_not_initialized);
}
- /* deflateParams will flush everything currently in the stream, corrupting
- * the heap unless it's empty. We therefore pretend to have a full output
- * buffer, forcing a Z_BUF_ERROR if there's anything left to be flushed. */
- d->s.avail_out = 0;
+ /* This is a bit of a hack; deflateParams flushes with Z_BLOCK which won't
+ * stop at a byte boundary, so we can't split this operation up, and we
+ * can't allocate a buffer large enough to fit it in one go since we have
+ * to support zlib versions that lack deflatePending.
+ *
+ * We therefore flush everything prior to this call to ensure that we are
+ * stopped on a byte boundary and have no pending data. We then hand it a
+ * dummy buffer to detect when this assumption doesn't hold (Hopefully
+ * never), and to smooth over an issue with zlib 1.2.11 which always
+ * returns Z_BUF_ERROR when d->s.avail_out is 0, regardless of whether
+ * there's any pending data or not. */
+
+ d->s.next_out = &dummy_buffer;
+ d->s.avail_out = 1;
+
res = deflateParams(&d->s, level, strategy);
+ if(d->s.avail_out == 0) {
+ return zlib_return(env, Z_STREAM_ERROR);
+ }
+
return zlib_return(env, res);
}
diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam
index f388bc723a..4ad5f37434 100644
--- a/erts/preloaded/ebin/zlib.beam
+++ b/erts/preloaded/ebin/zlib.beam
Binary files differ
diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl
index 03c9ae38a1..a4ef42204d 100644
--- a/erts/preloaded/src/zlib.erl
+++ b/erts/preloaded/src/zlib.erl
@@ -188,14 +188,13 @@ deflateReset_nif(_Z) ->
deflateParams(Z, Level0, Strategy0) ->
Level = arg_level(Level0),
Strategy = arg_strategy(Strategy0),
+ Progress = deflate(Z, <<>>, sync),
case deflateParams_nif(Z, Level, Strategy) of
- buf_error ->
- %% We had data left in the pipe; flush everything and stash it away
- %% for the next deflate call before trying again.
- Output = deflate(Z, <<>>, full),
- save_progress(Z, deflate, Output),
- deflateParams_nif(Z, Level, Strategy);
- Any -> Any
+ ok ->
+ save_progress(Z, deflate, Progress),
+ ok;
+ Other ->
+ Other
end.
deflateParams_nif(_Z, _Level, _Strategy) ->
erlang:nif_error(undef).