aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_nif.c53
-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
4 files changed, 56 insertions, 35 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index ac4ecd77e5..3ade17b10d 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -3426,36 +3426,38 @@ static int examine_iovec_term(Eterm list, UWord max_length, iovec_slice_t *resul
size = binary_size(binary);
binary_header = binary_val(binary);
- /* If we're a sub-binary we'll need to check our underlying binary to
- * determine whether we're on-heap or not. */
- if(thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) {
- ErlSubBin *sb = (ErlSubBin*)binary_header;
-
- /* Reject bitstrings */
- if((sb->bitoffs + sb->bitsize) > 0) {
- return 0;
+ if (size > 0) {
+ /* If we're a sub-binary we'll need to check our underlying binary
+ * to determine whether we're on-heap or not. */
+ if (thing_subtag(*binary_header) == SUB_BINARY_SUBTAG) {
+ ErlSubBin *sb = (ErlSubBin*)binary_header;
+
+ /* Reject bitstrings */
+ if((sb->bitoffs + sb->bitsize) > 0) {
+ return 0;
+ }
+
+ ASSERT(size <= binary_size(sb->orig));
+ binary_header = binary_val(sb->orig);
}
- ASSERT(size <= binary_size(sb->orig));
- binary_header = binary_val(sb->orig);
- }
-
- if(thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) {
- ASSERT(size <= ERL_ONHEAP_BIN_LIMIT);
+ if (thing_subtag(*binary_header) == HEAP_BINARY_SUBTAG) {
+ ASSERT(size <= ERL_ONHEAP_BIN_LIMIT);
- result->iovec_len += 1;
- result->onheap_size += size;
- } else {
- ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG);
+ result->iovec_len += 1;
+ result->onheap_size += size;
+ } else {
+ ASSERT(thing_subtag(*binary_header) == REFC_BINARY_SUBTAG);
- result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN;
- result->offheap_size += size;
+ result->iovec_len += 1 + size / MAX_SYSIOVEC_IOVLEN;
+ result->offheap_size += size;
+ }
}
result->sublist_length += 1;
lookahead = CDR(cell);
- if(result->sublist_length >= max_length) {
+ if (result->sublist_length >= max_length) {
break;
}
}
@@ -3488,6 +3490,10 @@ static void inspect_raw_binary_data(Eterm binary, ErlNifBinary *result) {
if (thing_subtag(*parent_header) == REFC_BINARY_SUBTAG) {
ProcBin *pb = (ProcBin*)parent_header;
+ if (pb->flags & (PB_IS_WRITABLE | PB_ACTIVE_WRITER)) {
+ erts_emasculate_writable_binary(pb);
+ }
+
ASSERT(pb->val != NULL);
ASSERT(byte_offset < pb->size);
ASSERT(&pb->bytes[byte_offset] >= (byte*)(pb->val)->orig_bytes);
@@ -3531,7 +3537,7 @@ static int fill_iovec_with_slice(ErlNifEnv *env,
/* If this isn't a refc binary, copy its contents to the onheap buffer
* and reference that instead. */
- if (raw_data.ref_bin == NULL) {
+ if (raw_data.size > 0 && raw_data.ref_bin == NULL) {
ASSERT(onheap_offset < onheap_data.size);
ASSERT(slice->onheap_size > 0);
@@ -3542,12 +3548,11 @@ static int fill_iovec_with_slice(ErlNifEnv *env,
raw_data.ref_bin = onheap_data.ref_bin;
}
- ASSERT(raw_data.ref_bin != NULL);
-
while (raw_data.size > 0) {
UWord chunk_len = MIN(raw_data.size, MAX_SYSIOVEC_IOVLEN);
ASSERT(iovec_idx < iovec->iovcnt);
+ ASSERT(raw_data.ref_bin != NULL);
iovec->iov[iovec_idx].iov_base = raw_data.data;
iovec->iov[iovec_idx].iov_len = chunk_len;
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).