diff options
author | Erlang/OTP <[email protected]> | 2017-02-07 09:46:15 +0100 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2017-02-07 09:46:15 +0100 |
commit | 67f7fc584d1f4a3e09fd279cd35502bf5942efb7 (patch) | |
tree | a2895d50df2f99efb31914403e744878b201725d /erts | |
parent | 51faafa9a20c4afa7944b8089b26f22c774bed19 (diff) | |
parent | e27119948fc6ab28bea81019720bddaac5b655a7 (diff) | |
download | otp-67f7fc584d1f4a3e09fd279cd35502bf5942efb7.tar.gz otp-67f7fc584d1f4a3e09fd279cd35502bf5942efb7.tar.bz2 otp-67f7fc584d1f4a3e09fd279cd35502bf5942efb7.zip |
Merge branch 'sverker/bin2term-zlib-bug/ERL-340/OTP-14159' into maint-19
* sverker/bin2term-zlib-bug/ERL-340/OTP-14159:
erts: Fix binary_to_term for compressed and zlib >= v1.2.9
Diffstat (limited to 'erts')
-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 beed847578..587c29e3b5 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1222,6 +1222,7 @@ typedef struct B2TContext_t { } u; } B2TContext; +static B2TContext* b2t_export_context(Process*, B2TContext* src); static uLongf binary2term_uncomp_size(byte* data, Sint size) { @@ -1254,7 +1255,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; @@ -1268,8 +1269,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); @@ -1286,16 +1287,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; @@ -1339,7 +1350,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) @@ -1485,7 +1496,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; |