diff options
author | Erlang/OTP <[email protected]> | 2017-02-01 18:32:27 +0100 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2017-02-01 18:32:27 +0100 |
commit | 5ac71f14c657fde3c01d4f15f1509e7fca6c9c96 (patch) | |
tree | 9bfbc4f4204ddf96cf7c02ef84a25feb04c6bd61 /erts/emulator | |
parent | f74baa361cf8b3af437f75aa1ec5a1886005261c (diff) | |
parent | e27119948fc6ab28bea81019720bddaac5b655a7 (diff) | |
download | otp-5ac71f14c657fde3c01d4f15f1509e7fca6c9c96.tar.gz otp-5ac71f14c657fde3c01d4f15f1509e7fca6c9c96.tar.bz2 otp-5ac71f14c657fde3c01d4f15f1509e7fca6c9c96.zip |
Merge branch 'sverker/bin2term-zlib-bug/ERL-340/OTP-14159' into maint-18
* sverker/bin2term-zlib-bug/ERL-340/OTP-14159:
erts: Fix binary_to_term for compressed and zlib >= v1.2.9
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/external.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index ffe3303796..31ec12cccf 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1206,6 +1206,7 @@ typedef struct B2TContext_t { } u; } B2TContext; +static B2TContext* b2t_export_context(Process*, B2TContext* src); static uLongf binary2term_uncomp_size(byte* data, Sint size) { @@ -1238,7 +1239,7 @@ static uLongf binary2term_uncomp_size(byte* data, Sint size) static ERTS_INLINE int binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size, - B2TContext* ctx) + B2TContext** ctxp, Process* p) { byte *bytes = data; Sint size = data_size; @@ -1252,8 +1253,8 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size, size--; if (size < 5 || *bytes != COMPRESSED) { state->extp = bytes; - if (ctx) - ctx->state = B2TSizeInit; + if (ctxp) + (*ctxp)->state = B2TSizeInit; } else { uLongf dest_len = (Uint32) get_int32(bytes+1); @@ -1270,16 +1271,26 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size, return -1; } state->extp = erts_alloc(ERTS_ALC_T_EXT_TERM_DATA, dest_len); - ctx->reds -= dest_len; + if (ctxp) + (*ctxp)->reds -= dest_len; } state->exttmp = 1; - if (ctx) { + if (ctxp) { + /* + * Start decompression by exporting trap context + * so we don't have to deal with deep-copying z_stream. + */ + B2TContext* ctx = b2t_export_context(p, *ctxp); + ASSERT(state = &(*ctxp)->b2ts); + state = &ctx->b2ts; + if (erl_zlib_inflate_start(&ctx->u.uc.stream, bytes, size) != Z_OK) return -1; ctx->u.uc.dbytes = state->extp; ctx->u.uc.dleft = dest_len; ctx->state = B2TUncompressChunk; + *ctxp = ctx; } else { uLongf dlen = dest_len; @@ -1323,7 +1334,7 @@ erts_binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size { Sint res; - if (binary2term_prepare(state, data, data_size, NULL) < 0 || + if (binary2term_prepare(state, data, data_size, NULL, NULL) < 0 || (res=decoded_size(state->extp, state->extp + state->extsize, 0, NULL)) < 0) { if (state->exttmp) @@ -1469,7 +1480,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binar if (ctx->aligned_alloc) { ctx->reds -= bin_size / 8; } - if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, ctx) < 0) { + if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, &ctx, p) < 0) { ctx->state = B2TBadArg; } break; |