@@ -1193,6 +1193,7 @@ typedef struct B2TContext_t {
1193
1193
} u ;
1194
1194
} B2TContext ;
1195
1195
1196
+ static B2TContext * b2t_export_context (Process * , B2TContext * src );
1196
1197
1197
1198
static uLongf binary2term_uncomp_size (byte * data , Sint size )
1198
1199
{
@@ -1225,7 +1226,7 @@ static uLongf binary2term_uncomp_size(byte* data, Sint size)
1225
1226
1226
1227
static ERTS_INLINE int
1227
1228
binary2term_prepare (ErtsBinary2TermState * state , byte * data , Sint data_size ,
1228
- B2TContext * ctx )
1229
+ B2TContext * * ctxp , Process * p )
1229
1230
{
1230
1231
byte * bytes = data ;
1231
1232
Sint size = data_size ;
@@ -1239,8 +1240,8 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
1239
1240
size -- ;
1240
1241
if (size < 5 || * bytes != COMPRESSED ) {
1241
1242
state -> extp = bytes ;
1242
- if (ctx )
1243
- ctx -> state = B2TSizeInit ;
1243
+ if (ctxp )
1244
+ ( * ctxp ) -> state = B2TSizeInit ;
1244
1245
}
1245
1246
else {
1246
1247
uLongf dest_len = (Uint32 ) get_int32 (bytes + 1 );
@@ -1257,16 +1258,26 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
1257
1258
return -1 ;
1258
1259
}
1259
1260
state -> extp = erts_alloc (ERTS_ALC_T_EXT_TERM_DATA , dest_len );
1260
- ctx -> reds -= dest_len ;
1261
+ if (ctxp )
1262
+ (* ctxp )-> reds -= dest_len ;
1261
1263
}
1262
1264
state -> exttmp = 1 ;
1263
- if (ctx ) {
1265
+ if (ctxp ) {
1266
+ /*
1267
+ * Start decompression by exporting trap context
1268
+ * so we don't have to deal with deep-copying z_stream.
1269
+ */
1270
+ B2TContext * ctx = b2t_export_context (p , * ctxp );
1271
+ ASSERT (state = & (* ctxp )-> b2ts );
1272
+ state = & ctx -> b2ts ;
1273
+
1264
1274
if (erl_zlib_inflate_start (& ctx -> u .uc .stream , bytes , size ) != Z_OK )
1265
1275
return -1 ;
1266
1276
1267
1277
ctx -> u .uc .dbytes = state -> extp ;
1268
1278
ctx -> u .uc .dleft = dest_len ;
1269
1279
ctx -> state = B2TUncompressChunk ;
1280
+ * ctxp = ctx ;
1270
1281
}
1271
1282
else {
1272
1283
uLongf dlen = dest_len ;
@@ -1308,7 +1319,7 @@ erts_binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size
1308
1319
{
1309
1320
Sint res ;
1310
1321
1311
- if (binary2term_prepare (state , data , data_size , NULL ) < 0 ||
1322
+ if (binary2term_prepare (state , data , data_size , NULL , NULL ) < 0 ||
1312
1323
(res = decoded_size (state -> extp , state -> extp + state -> extsize , 0 , NULL )) < 0 ) {
1313
1324
1314
1325
if (state -> exttmp )
@@ -1435,7 +1446,7 @@ static Eterm binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binary* con
1435
1446
if (ctx -> aligned_alloc ) {
1436
1447
ctx -> reds -= bin_size / 8 ;
1437
1448
}
1438
- if (binary2term_prepare (& ctx -> b2ts , bytes , bin_size , ctx ) < 0 ) {
1449
+ if (binary2term_prepare (& ctx -> b2ts , bytes , bin_size , & ctx , p ) < 0 ) {
1439
1450
ctx -> state = B2TBadArg ;
1440
1451
}
1441
1452
break ;
0 commit comments