From b4d560dd52309aaabd5a7374fc745e6210fe7e18 Mon Sep 17 00:00:00 2001 From: "C. Scott Ananian" Date: Sat, 26 Oct 2013 01:20:41 -0400 Subject: [PATCH] Fix a bunch of memory leaks. Found by compiling PHP with --enable-debug. --- v8js.cc | 4 ++++ v8js_methods.cc | 25 ++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/v8js.cc b/v8js.cc index 988847b..a5b133e 100644 --- a/v8js.cc +++ b/v8js.cc @@ -512,6 +512,10 @@ static void php_v8js_free_storage(void *object TSRMLS_DC) /* {{{ */ zval_ptr_dtor(&c->pending_exception); } + if (c->module_loader) { + zval_ptr_dtor(&c->module_loader); + } + /* Delete PHP global object from JavaScript */ if (!c->context.IsEmpty()) { v8::Locker locker(c->isolate); diff --git a/v8js_methods.cc b/v8js_methods.cc index 0c0d5f2..133e4f9 100644 --- a/v8js_methods.cc +++ b/v8js_methods.cc @@ -234,6 +234,7 @@ V8JS_METHOD(require) for (std::vector::iterator it = c->modules_stack.begin(); it != c->modules_stack.end(); ++it) { if (!strcmp(*it, normalised_module_id)) { + efree(normalised_module_id); efree(normalised_path); info.GetReturnValue().Set(v8::ThrowException(V8JS_SYM("Module cyclic dependency"))); @@ -243,6 +244,7 @@ V8JS_METHOD(require) // If we have already loaded and cached this module then use it if (V8JSG(modules_loaded).count(normalised_module_id) > 0) { + efree(normalised_module_id); efree(normalised_path); info.GetReturnValue().Set(V8JSG(modules_loaded)[normalised_module_id]); @@ -251,22 +253,26 @@ V8JS_METHOD(require) // Callback to PHP to load the module code - zval module_code; + zval *module_code; zval *normalised_path_zend; MAKE_STD_ZVAL(normalised_path_zend); ZVAL_STRING(normalised_path_zend, normalised_module_id, 1); - zval* params[] = { normalised_path_zend }; - if (FAILURE == call_user_function(EG(function_table), NULL, c->module_loader, &module_code, 1, params TSRMLS_CC)) { + zval **params[1] = {&normalised_path_zend}; + if (FAILURE == call_user_function_ex(EG(function_table), NULL, c->module_loader, &module_code, 1, params, 0, NULL TSRMLS_CC)) { + zval_ptr_dtor(&normalised_path_zend); + efree(normalised_module_id); efree(normalised_path); info.GetReturnValue().Set(v8::ThrowException(V8JS_SYM("Module loader callback failed"))); return; } + zval_ptr_dtor(&normalised_path_zend); // Check if an exception was thrown if (EG(exception)) { + efree(normalised_module_id); efree(normalised_path); // Clear the PHP exception and throw it in V8 instead @@ -276,12 +282,14 @@ V8JS_METHOD(require) } // Convert the return value to string - if (Z_TYPE(module_code) != IS_STRING) { - convert_to_string(&module_code); + if (Z_TYPE_P(module_code) != IS_STRING) { + convert_to_string(module_code); } // Check that some code has been returned - if (!strlen(Z_STRVAL(module_code))) { + if (Z_STRLEN_P(module_code)==0) { + zval_ptr_dtor(&module_code); + efree(normalised_module_id); efree(normalised_path); info.GetReturnValue().Set(v8::ThrowException(V8JS_SYM("Module loader callback did not return code"))); @@ -321,13 +329,15 @@ V8JS_METHOD(require) // Set script identifier v8::Local sname = V8JS_SYM("require"); - v8::Local source = V8JS_STR(Z_STRVAL(module_code)); + v8::Local source = V8JS_STRL(Z_STRVAL_P(module_code), Z_STRLEN_P(module_code)); + zval_ptr_dtor(&module_code); // Create and compile script v8::Local script = v8::Script::New(source, sname); // The script will be empty if there are compile errors if (script.IsEmpty()) { + efree(normalised_module_id); efree(normalised_path); info.GetReturnValue().Set(v8::ThrowException(V8JS_SYM("Module script compile failed"))); return; @@ -345,6 +355,7 @@ V8JS_METHOD(require) c->modules_stack.pop_back(); c->modules_base.pop_back(); + efree(normalised_module_id); efree(normalised_path); // Script possibly terminated, return immediately