[PATCH v2 3/3] jscript: Release all globals when the script ctx is destroyed or re-initialized.

Gabriel Ivăncescu gabrielopcode at gmail.com
Tue May 31 09:56:28 CDT 2022


Most of these globals were leaking before as they were never freed at
all. Also, they have to be freed during script ctx destruction because an
unintialized script might still make use of them (e.g. retrieving a builtin
function via PROPERTYGET requires ctx->function_constr to be available).

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

The previous patch already has tests for that builtin PROPERTYGET thing
(with the DISPID obtained before setting it to uninitialized).

 dlls/jscript/global.c  |  1 +
 dlls/jscript/jscript.c | 27 +++++++++++------------
 dlls/jscript/jscript.h | 49 ++++++++++++++++++++++++------------------
 3 files changed, 41 insertions(+), 36 deletions(-)

diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c
index c0ed954..1fe68b2 100644
--- a/dlls/jscript/global.c
+++ b/dlls/jscript/global.c
@@ -1085,6 +1085,7 @@ HRESULT init_global(script_ctx_t *ctx)
 
     if(ctx->global)
         return S_OK;
+    script_globals_release(ctx);
 
     hres = create_dispex(ctx, &JSGlobal_info, NULL, &ctx->global);
     if(FAILED(hres))
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c
index d6028e6..3189528 100644
--- a/dlls/jscript/jscript.c
+++ b/dlls/jscript/jscript.c
@@ -71,11 +71,23 @@ typedef struct {
     jsexcept_t ei;
 } JScriptError;
 
+void script_globals_release(script_ctx_t *ctx)
+{
+    unsigned i;
+    for(i = 0; i < ARRAY_SIZE(ctx->global_objects); i++) {
+        if(ctx->global_objects[i]) {
+            jsdisp_release(ctx->global_objects[i]);
+            ctx->global_objects[i] = NULL;
+        }
+    }
+}
+
 void script_release(script_ctx_t *ctx)
 {
     if(--ctx->ref)
         return;
 
+    script_globals_release(ctx);
     jsval_release(ctx->acc);
     if(ctx->cc)
         release_cc(ctx->cc);
@@ -483,21 +495,6 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
                 This->ctx->site = NULL;
             }
 
-            if(This->ctx->map_prototype) {
-                jsdisp_release(This->ctx->map_prototype);
-                This->ctx->map_prototype = NULL;
-            }
-
-            if(This->ctx->set_prototype) {
-                jsdisp_release(This->ctx->set_prototype);
-                This->ctx->set_prototype = NULL;
-            }
-
-            if(This->ctx->object_prototype) {
-                jsdisp_release(This->ctx->object_prototype);
-                This->ctx->object_prototype = NULL;
-            }
-
             if(This->ctx->global) {
                 jsdisp_release(This->ctx->global);
                 This->ctx->global = NULL;
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 000bcc2..c5c9043 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -388,29 +388,36 @@ struct _script_ctx_t {
     DWORD last_match_length;
 
     jsdisp_t *global;
-    jsdisp_t *function_constr;
-    jsdisp_t *array_constr;
-    jsdisp_t *bool_constr;
-    jsdisp_t *date_constr;
-    jsdisp_t *enumerator_constr;
-    jsdisp_t *error_constr;
-    jsdisp_t *eval_error_constr;
-    jsdisp_t *range_error_constr;
-    jsdisp_t *reference_error_constr;
-    jsdisp_t *regexp_error_constr;
-    jsdisp_t *syntax_error_constr;
-    jsdisp_t *type_error_constr;
-    jsdisp_t *uri_error_constr;
-    jsdisp_t *number_constr;
-    jsdisp_t *object_constr;
-    jsdisp_t *object_prototype;
-    jsdisp_t *regexp_constr;
-    jsdisp_t *string_constr;
-    jsdisp_t *vbarray_constr;
-    jsdisp_t *map_prototype;
-    jsdisp_t *set_prototype;
+    union {
+        struct {
+            jsdisp_t *function_constr;
+            jsdisp_t *array_constr;
+            jsdisp_t *bool_constr;
+            jsdisp_t *date_constr;
+            jsdisp_t *enumerator_constr;
+            jsdisp_t *error_constr;
+            jsdisp_t *eval_error_constr;
+            jsdisp_t *range_error_constr;
+            jsdisp_t *reference_error_constr;
+            jsdisp_t *regexp_error_constr;
+            jsdisp_t *syntax_error_constr;
+            jsdisp_t *type_error_constr;
+            jsdisp_t *uri_error_constr;
+            jsdisp_t *number_constr;
+            jsdisp_t *object_constr;
+            jsdisp_t *object_prototype;
+            jsdisp_t *regexp_constr;
+            jsdisp_t *string_constr;
+            jsdisp_t *vbarray_constr;
+            jsdisp_t *map_prototype;
+            jsdisp_t *set_prototype;
+        };
+        jsdisp_t *global_objects[21];
+    };
 };
+C_ASSERT(RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, set_prototype) == RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, global_objects));
 
+void script_globals_release(script_ctx_t *ctx) DECLSPEC_HIDDEN;
 void script_release(script_ctx_t*) DECLSPEC_HIDDEN;
 
 static inline void script_addref(script_ctx_t *ctx)
-- 
2.34.1




More information about the wine-devel mailing list