From: Dmitry Volyntsev Date: Tue, 22 Sep 2026 04:13:22 +0000 (-0700) Subject: Zlib: copy QJS dictionaries before conversion X-Git-Tag: 1.0.2~12 X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=7922554d7099ac98374151674f9f5ffd0116a29f;p=njs.git Zlib: copy QJS dictionaries before conversion Copy dictionary bytes before converting other JavaScript arguments so their backing storage cannot be invalidated during zlib setup. --- diff --git a/external/qjs_zlib_module.c b/external/qjs_zlib_module.c index a980c9b2..20218c01 100644 --- a/external/qjs_zlib_module.c +++ b/external/qjs_zlib_module.c @@ -70,7 +70,8 @@ qjs_zlib_ext_deflate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int raw) { int rc, level, mem_level, strategy, window_bits; - size_t chunk_size; + u_char *dictionary_copy; + size_t chunk_size, dictionary_length; uint64_t chunk_size_value; JSValue ret, options; z_stream stream; @@ -86,6 +87,8 @@ qjs_zlib_ext_deflate(JSContext *ctx, JSValueConst this_val, int argc, NJS_CHB_CTX_INIT(&chain, ctx); dictionary.start = NULL; dictionary.length = 0; + dictionary_copy = NULL; + dictionary_length = 0; stream.opaque = NULL; options = argv[1]; @@ -213,11 +216,23 @@ qjs_zlib_ext_deflate(JSContext *ctx, JSValueConst this_val, int argc, if (rc != 0) { return JS_EXCEPTION; } + + dictionary_copy = js_malloc(ctx, dictionary.length); + if (dictionary_copy == NULL && dictionary.length != 0) { + qjs_bytes_free(ctx, &dictionary); + return JS_EXCEPTION; + } + + memcpy(dictionary_copy, dictionary.start, dictionary.length); + dictionary_length = dictionary.length; + qjs_bytes_free(ctx, &dictionary); + dictionary.start = NULL; } } rc = qjs_to_bytes(ctx, &bytes, argv[0]); if (rc != 0) { + js_free(ctx, dictionary_copy); return JS_EXCEPTION; } @@ -235,8 +250,8 @@ qjs_zlib_ext_deflate(JSContext *ctx, JSValueConst this_val, int argc, goto fail; } - if (dictionary.start != NULL) { - rc = deflateSetDictionary(&stream, dictionary.start, dictionary.length); + if (dictionary_copy != NULL) { + rc = deflateSetDictionary(&stream, dictionary_copy, dictionary_length); if (rc != Z_OK) { JS_ThrowInternalError(ctx, "deflateSetDictionary() failed"); goto fail; @@ -267,9 +282,7 @@ qjs_zlib_ext_deflate(JSContext *ctx, JSValueConst this_val, int argc, qjs_bytes_free(ctx, &bytes); - if (dictionary.start != NULL) { - qjs_bytes_free(ctx, &dictionary); - } + js_free(ctx, dictionary_copy); ret = qjs_buffer_chb_alloc(ctx, &chain); @@ -281,9 +294,7 @@ fail: qjs_bytes_free(ctx, &bytes); - if (dictionary.start != NULL) { - qjs_bytes_free(ctx, &dictionary); - } + js_free(ctx, dictionary_copy); if (stream.opaque != NULL) { deflateEnd(&stream); @@ -302,7 +313,8 @@ qjs_zlib_ext_inflate(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int raw) { int rc, window_bits; - size_t chunk_size; + u_char *dictionary_copy; + size_t chunk_size, dictionary_length; uint64_t chunk_size_value; JSValue ret, options; z_stream stream; @@ -315,6 +327,8 @@ qjs_zlib_ext_inflate(JSContext *ctx, JSValueConst this_val, int argc, NJS_CHB_CTX_INIT(&chain, ctx); dictionary.start = NULL; dictionary.length = 0; + dictionary_copy = NULL; + dictionary_length = 0; stream.opaque = NULL; options = argv[1]; @@ -379,11 +393,23 @@ qjs_zlib_ext_inflate(JSContext *ctx, JSValueConst this_val, int argc, if (rc != 0) { return JS_EXCEPTION; } + + dictionary_copy = js_malloc(ctx, dictionary.length); + if (dictionary_copy == NULL && dictionary.length != 0) { + qjs_bytes_free(ctx, &dictionary); + return JS_EXCEPTION; + } + + memcpy(dictionary_copy, dictionary.start, dictionary.length); + dictionary_length = dictionary.length; + qjs_bytes_free(ctx, &dictionary); + dictionary.start = NULL; } } rc = qjs_to_bytes(ctx, &bytes, argv[0]); if (rc != 0) { + js_free(ctx, dictionary_copy); return JS_EXCEPTION; } @@ -400,8 +426,8 @@ qjs_zlib_ext_inflate(JSContext *ctx, JSValueConst this_val, int argc, goto fail; } - if (dictionary.start != NULL) { - rc = inflateSetDictionary(&stream, dictionary.start, dictionary.length); + if (dictionary_copy != NULL) { + rc = inflateSetDictionary(&stream, dictionary_copy, dictionary_length); if (rc != Z_OK) { JS_ThrowInternalError(ctx, "inflateSetDictionary() failed"); goto fail; @@ -440,9 +466,7 @@ qjs_zlib_ext_inflate(JSContext *ctx, JSValueConst this_val, int argc, qjs_bytes_free(ctx, &bytes); - if (dictionary.start != NULL) { - qjs_bytes_free(ctx, &dictionary); - } + js_free(ctx, dictionary_copy); ret = qjs_buffer_chb_alloc(ctx, &chain); @@ -454,6 +478,8 @@ fail: qjs_bytes_free(ctx, &bytes); + js_free(ctx, dictionary_copy); + if (dictionary.start != NULL) { qjs_bytes_free(ctx, &dictionary); }