aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/nifs
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2017-11-09 16:15:40 +0100
committerErlang/OTP <[email protected]>2017-11-09 16:15:40 +0100
commitedfbdc2ab46b44d83da7e3de2ae601055a3bcc2f (patch)
tree6fd54f81f11f9335eb69026d3b3e8632ce17fb73 /erts/emulator/nifs
parent3e8c1ff94c0a73df71daadd4eb782c21c49f22d9 (diff)
parente96969083dbfebfaaa600d2ba6c2cf6d5a690cbe (diff)
downloadotp-edfbdc2ab46b44d83da7e3de2ae601055a3bcc2f.tar.gz
otp-edfbdc2ab46b44d83da7e3de2ae601055a3bcc2f.tar.bz2
otp-edfbdc2ab46b44d83da7e3de2ae601055a3bcc2f.zip
Merge branch 'john/erts/zlib-1.2.11-fixes/OTP-14751' into maint-20
* john/erts/zlib-1.2.11-fixes/OTP-14751: Avoid WindowBits=8 as per the manual Fix deflateParams on zlib 1.2.11
Diffstat (limited to 'erts/emulator/nifs')
-rw-r--r--erts/emulator/nifs/common/zlib_nif.c25
1 files changed, 21 insertions, 4 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);
}