]> granicus.if.org Git - php/commitdiff
Cleanup shutdown, enable proper memory leak displaying
authorBob Weinand <bobwei9@hotmail.com>
Fri, 24 Jul 2015 15:17:09 +0000 (17:17 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Fri, 24 Jul 2015 15:17:26 +0000 (17:17 +0200)
phpdbg should not memory leak...

13 files changed:
Zend/zend_opcode.c
Zend/zend_portability.h
main/php_variables.c
main/php_variables.h
sapi/phpdbg/phpdbg.c
sapi/phpdbg/phpdbg.h
sapi/phpdbg/phpdbg_bp.c
sapi/phpdbg/phpdbg_cmd.c
sapi/phpdbg/phpdbg_list.c
sapi/phpdbg/phpdbg_out.c
sapi/phpdbg/phpdbg_prompt.c
sapi/phpdbg/phpdbg_prompt.h
sapi/phpdbg/phpdbg_utils.c

index 90afc6a9851a4426fe1ebe22aafb6064111093e2..ba952a486791398829a8c67bf59b3b456a0b8087 100644 (file)
@@ -343,13 +343,14 @@ ZEND_API zend_bool destroy_op_array(zend_op_array *op_array)
 
        if (op_array->static_variables &&
            !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
-           if (--GC_REFCOUNT(op_array->static_variables) == 0) {
+               if (--GC_REFCOUNT(op_array->static_variables) == 0) {
                        zend_array_destroy(op_array->static_variables);
                }
        }
 
        if (op_array->run_time_cache && !op_array->function_name) {
                efree(op_array->run_time_cache);
+               op_array->run_time_cache = NULL;
        }
 
        if (!op_array->refcount) {
index 2464f48c0fa76008bb852ad53d17d49ba1105777..99069e57e1228aec3de9afd63ee0f8bbc1a1d23a 100644 (file)
@@ -175,7 +175,7 @@ char *alloca();
 # endif
 #endif
 
-#if ZEND_GCC_VERSION >= 2096
+#if ZEND_GCC_VERSION >= 2096 || __has_attribute(__malloc__)
 # define ZEND_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
 #else
 # define ZEND_ATTRIBUTE_MALLOC
@@ -221,12 +221,16 @@ char *alloca();
 # define ZEND_ATTRIBUTE_UNUSED_LABEL
 #endif
 
-#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
-# define ZEND_FASTCALL __attribute__((fastcall))
-#elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
-# define ZEND_FASTCALL __fastcall
-#elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
-# define ZEND_FASTCALL __vectorcall
+#if !ZEND_DEBUG
+# if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
+#  define ZEND_FASTCALL __attribute__((fastcall))
+# elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER == 1700
+#  define ZEND_FASTCALL __fastcall
+# elif defined(_MSC_VER) && _MSC_VER >= 1800 && !defined(__clang__)
+#  define ZEND_FASTCALL __vectorcall
+# else
+#  define ZEND_FASTCALL
+# endif
 #else
 # define ZEND_FASTCALL
 #endif
index bcc5997faa16c53130b0de1ffa178938d63517ee..ebc060bb1b11acf03baa35922d6cdfc65ea5c5f3 100644 (file)
@@ -524,7 +524,7 @@ zend_bool php_std_auto_global_callback(char *name, uint name_len)
 
 /* {{{ php_build_argv
  */
-static void php_build_argv(char *s, zval *track_vars_array)
+PHPAPI void php_build_argv(char *s, zval *track_vars_array)
 {
        zval arr, argc, tmp;
        int count = 0;
index a80c152c837823865febeceb09f29b895a721600..d34a09035eae6fdd6271ac390c4ec794468151fa 100644 (file)
@@ -41,6 +41,7 @@ PHPAPI void php_register_variable(char *var, char *val, zval *track_vars_array);
 PHPAPI void php_register_variable_safe(char *var, char *val, size_t val_len, zval *track_vars_array);
 PHPAPI void php_register_variable_ex(char *var, zval *val, zval *track_vars_array);
 
+PHPAPI void php_build_argv(char *s, zval *track_vars_array);
 PHPAPI int php_hash_environment(void);
 END_EXTERN_C()
 
index ecfe7a9249c1e5f5c9116a5e15b236190955e292..12a2c94962ea7796372048031db8b0c515c4926e 100644 (file)
@@ -72,12 +72,6 @@ PHP_INI_END()
 static zend_bool phpdbg_booted = 0;
 static zend_bool phpdbg_fully_started = 0;
 
-#if PHP_VERSION_ID >= 50500
-void (*zend_execute_old)(zend_execute_data *execute_data);
-#else
-void (*zend_execute_old)(zend_op_array *op_array);
-#endif
-
 static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */
 {
        pg->prompt[0] = NULL;
@@ -102,6 +96,7 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */
        pg->sapi_name_ptr = NULL;
        pg->socket_fd = -1;
        pg->socket_server_fd = -1;
+       pg->unclean_eval = 0;
 
        pg->req_id = 0;
        pg->err_buf.active = 0;
@@ -126,13 +121,7 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */
        ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL);
        REGISTER_INI_ENTRIES();
 
-#if PHP_VERSION_ID >= 50500
-       zend_execute_old = zend_execute_ex;
        zend_execute_ex = phpdbg_execute_ex;
-#else
-       zend_execute_old = zend_execute;
-       zend_execute = phpdbg_execute_ex;
-#endif
 
        REGISTER_STRINGL_CONSTANT("PHPDBG_VERSION", PHPDBG_VERSION, sizeof(PHPDBG_VERSION)-1, CONST_CS|CONST_PERSISTENT);
 
@@ -151,43 +140,42 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */
 static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */
 {
        zend_hash_destroy(Z_ARRVAL_P(brake));
+       efree(Z_ARRVAL_P(brake));
 } /* }}} */
 
 static void php_phpdbg_destroy_bp_symbol(zval *brake) /* {{{ */
 {
        efree((char *) ((phpdbg_breaksymbol_t *) Z_PTR_P(brake))->symbol);
+       efree(Z_PTR_P(brake));
 } /* }}} */
 
 static void php_phpdbg_destroy_bp_opcode(zval *brake) /* {{{ */
 {
        efree((char *) ((phpdbg_breakop_t *) Z_PTR_P(brake))->name);
+       efree(Z_PTR_P(brake));
 } /* }}} */
 
-
 static void php_phpdbg_destroy_bp_methods(zval *brake) /* {{{ */
 {
        zend_hash_destroy(Z_ARRVAL_P(brake));
+       efree(Z_ARRVAL_P(brake));
 } /* }}} */
 
 static void php_phpdbg_destroy_bp_condition(zval *data) /* {{{ */
 {
        phpdbg_breakcond_t *brake = (phpdbg_breakcond_t *) Z_PTR_P(data);
 
-       if (brake) {
-               if (brake->ops) {
-
-                       destroy_op_array(brake->ops);
-                       efree(brake->ops);
-               }
-               efree((char*) brake->code);
+       if (brake->ops) {
+               destroy_op_array(brake->ops);
+               efree(brake->ops);
        }
+       efree((char*) brake->code);
+       efree(brake);
 } /* }}} */
 
 static void php_phpdbg_destroy_registered(zval *data) /* {{{ */
 {
        zend_function *function = (zend_function *) Z_PTR_P(data);
-
-
        destroy_zend_function(function);
 } /* }}} */
 
@@ -215,6 +203,7 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */
 static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
 {
        zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]);
+       zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]);
        zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]);
        zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]);
        zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]);
@@ -240,16 +229,6 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */
                PHPDBG_G(exec) = NULL;
        }
 
-       if (PHPDBG_G(prompt)[0]) {
-               free(PHPDBG_G(prompt)[0]);
-       }
-       if (PHPDBG_G(prompt)[1]) {
-               free(PHPDBG_G(prompt)[1]);
-       }
-
-       PHPDBG_G(prompt)[0] = NULL;
-       PHPDBG_G(prompt)[1] = NULL;
-
        if (PHPDBG_G(oplog)) {
                fclose(PHPDBG_G(oplog));
                PHPDBG_G(oplog) = NULL;
@@ -847,25 +826,8 @@ static void php_sapi_phpdbg_log_message(char *message) /* {{{ */
 
 static int php_sapi_phpdbg_deactivate(void) /* {{{ */
 {
-       if ((PHPDBG_G(flags) & PHPDBG_IS_STOPPING) == PHPDBG_IS_CLEANING) {
-               zend_phpdbg_globals *pg = PHPDBG_G(backup) = calloc(1, sizeof(zend_phpdbg_globals));
-
-               php_phpdbg_globals_ctor(pg);
-
-               pg->exec = zend_strndup(PHPDBG_G(exec), PHPDBG_G(exec_len));
-               pg->exec_len = PHPDBG_G(exec_len);
-               pg->oplog = PHPDBG_G(oplog);
-               pg->prompt[0] = PHPDBG_G(prompt)[0];
-               pg->prompt[1] = PHPDBG_G(prompt)[1];
-               memcpy(pg->colors, PHPDBG_G(colors), sizeof(pg->colors));
-               pg->eol = PHPDBG_G(eol);
-               pg->input_buflen = PHPDBG_G(input_buflen);
-               memcpy(pg->input_buffer, PHPDBG_G(input_buffer), pg->input_buflen);
-               pg->flags = PHPDBG_G(flags) & PHPDBG_PRESERVE_FLAGS_MASK;
-       }
-
        fflush(stdout);
-       if(SG(request_info).argv0) {
+       if (SG(request_info).argv0) {
                free(SG(request_info).argv0);
                SG(request_info).argv0 = NULL;
        }
@@ -946,14 +908,8 @@ static size_t phpdbg_stdiop_write(php_stream *stream, const char *buf, size_t co
        return PHPDBG_G(php_stdiop_write)(stream, buf, count);
 }
 
-#if PHP_VERSION_ID >= 50700
 static inline void php_sapi_phpdbg_flush(void *context)  /* {{{ */
 {
-#else
-static inline void php_sapi_phpdbg_flush(void *context)  /* {{{ */
-{
-#endif
-
        if (!phpdbg_active_sigsafe_mem()) {
                fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr);
        }
@@ -1083,7 +1039,6 @@ const char phpdbg_ini_hardcoded[] =
 /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */
 #define INI_DEFAULT(name, value) \
        ZVAL_STRINGL(&tmp, value, sizeof(value) - 1); \
-       Z_SET_REFCOUNT(tmp, 0); \
        zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp);
 
 void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */
@@ -1269,37 +1224,55 @@ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) /* {{{ */
 } /* }}} */
 #endif
 
-static inline zend_mm_heap *phpdbg_mm_get_heap() /* {{{ */
-{
-       zend_mm_heap *mm_heap;
-
-
-       mm_heap = zend_mm_set_heap(NULL);
-       zend_mm_set_heap(mm_heap);
 
-       return mm_heap;
-} /* }}} */
+/* A bit dark magic in order to have meaningful allocator adresses */
+#if ZEND_DEBUG && __has_builtin(__builtin_frame_address)
+#define FETCH_PARENT_FILELINE(argsize) \
+       char *__zend_filename, *__zend_orig_filename; \
+       uint __zend_lineno, __zend_orig_lineno; \
+       void *parent = __builtin_frame_address(1U); \
+       parent -= ZEND_MM_ALIGNED_SIZE(sizeof(void *)); /* remove frame pointer adress */ \
+       parent -= (argsize); /* size of first arguments */ \
+       parent -= sizeof(char *); /* filename */ \
+       __zend_filename = *(char **) parent; \
+       parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
+       parent -= sizeof(uint); /* lineno */ \
+       __zend_lineno = *(uint *) parent; \
+       parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
+       parent -= sizeof(char *); /* orig_filename */ \
+       __zend_orig_filename = *(char **) parent; \
+       parent = (void *) ((intptr_t) parent & ZEND_MM_ALIGNMENT_MASK); /* realign */ \
+       parent -= sizeof(uint); /* orig_lineno */ \
+       __zend_orig_lineno = *(uint *) parent;
+#elif ZEND_DEBUG
+#define FETCH_PARENT_FILELINE() \
+       char *__zend_filename = __FILE__, *__zend_orig_filename = NULL; \
+       uint __zend_lineno = __LINE__, __zend_orig_lineno = 0;
+#endif
 
 void *phpdbg_malloc_wrapper(size_t size) /* {{{ */
 {
-       return zend_mm_alloc(phpdbg_mm_get_heap(), size);
+       FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(size)));
+       return _zend_mm_alloc(zend_mm_get_heap(), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
 } /* }}} */
 
 void phpdbg_free_wrapper(void *p) /* {{{ */
 {
-       zend_mm_heap *heap = phpdbg_mm_get_heap();
+       zend_mm_heap *heap = zend_mm_get_heap();
        if (UNEXPECTED(heap == p)) {
                /* TODO: heap maybe allocated by mmap(zend_mm_init) or malloc(USE_ZEND_ALLOC=0) 
                 * let's prevent it from segfault for now
                 */
        } else {
-               zend_mm_free(heap, p);
+               FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(p)));
+               return _zend_mm_free(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
        }
 } /* }}} */
 
 void *phpdbg_realloc_wrapper(void *ptr, size_t size) /* {{{ */
 {
-       return zend_mm_realloc(phpdbg_mm_get_heap(), ptr, size);
+       FETCH_PARENT_FILELINE(ZEND_MM_ALIGNED_SIZE(sizeof(ptr)) + ZEND_MM_ALIGNED_SIZE(sizeof(size)));
+       return _zend_mm_realloc(zend_mm_get_heap(), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
 } /* }}} */
 
 int main(int argc, char **argv) /* {{{ */
@@ -1333,6 +1306,7 @@ int main(int argc, char **argv) /* {{{ */
        FILE* stream = NULL;
        char *print_opline_func;
        zend_bool ext_stmt = 0;
+       zend_bool use_mm_wrappers = 0;
 
 #ifdef ZTS
        void ***tsrm_ls;
@@ -1624,6 +1598,7 @@ phpdbg_main:
 #else
                        phpdbg_globals = *settings;
 #endif
+                       free(settings);
                }
 
                /* setup remote server if necessary */
@@ -1641,21 +1616,17 @@ phpdbg_main:
                        remote = 1;
                }
 
-               mm_heap = phpdbg_mm_get_heap();
+               mm_heap = zend_mm_get_heap();
                zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc);
 
-               if (!_malloc) {
+               use_mm_wrappers = !_malloc && !_realloc && !_free;
+
+               if (use_mm_wrappers) {
                        _malloc = phpdbg_malloc_wrapper;
-               }
-               if (!_realloc) {
                        _realloc = phpdbg_realloc_wrapper;
-               }
-               if (!_free) {
                        _free = phpdbg_free_wrapper;
                }
 
-               zend_activate();
-
                phpdbg_init_list();
 
                PHPDBG_G(original_free_function) = _free;
@@ -1692,9 +1663,14 @@ phpdbg_main:
                php_output_activate();
                php_output_deactivate();
 
+               if (SG(sapi_headers).mimetype) {
+                       efree(SG(sapi_headers).mimetype);
+                       SG(sapi_headers).mimetype = NULL;
+               }
+
                php_output_activate();
 
-               if (php_request_startup() == SUCCESS) {
+               {
                        int i;
 
                        SG(request_info).argc = argc - php_optind + 1;
@@ -1703,8 +1679,11 @@ phpdbg_main:
                                SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]);
                        }
                        SG(request_info).argv[0] = PHPDBG_G(exec) ? estrdup(PHPDBG_G(exec)) : estrdup("");
+               }
 
-                       php_hash_environment();
+               if (php_request_startup() == FAILURE) {
+                       PUTS("Could not startup");
+                       return 1;
                }
 
                /* do not install sigint handlers for remote consoles */
@@ -1721,7 +1700,7 @@ phpdbg_main:
                }
 #endif
 
-               PG(modules_activated) = 0;
+//             PG(modules_activated) = 0;
 
 #ifndef _WIN32
                /* setup io here */
@@ -1842,7 +1821,6 @@ phpdbg_main:
 #ifndef _WIN32
 phpdbg_interact:
 #endif
-
                /* phpdbg main() */
                do {
                        zend_try {
@@ -1857,6 +1835,7 @@ phpdbg_interact:
                                        }
                                }
 
+                               CG(unclean_shutdown) = 0;
                                phpdbg_interactive(1);
                        } zend_catch {
                                if ((PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) {
@@ -1900,16 +1879,6 @@ phpdbg_interact:
                } while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING));
 
 
-               if (PHPDBG_G(exec) && (PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) {
-                       exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */
-               }
-
-               /* this must be forced */
-               CG(unclean_shutdown) = 0;
-
-               /* this is just helpful */
-               PG(report_memleaks) = 0;
-
 #ifndef _WIN32
 phpdbg_out:
                if ((PHPDBG_G(flags) & PHPDBG_IS_DISCONNECTED)) {
@@ -1939,16 +1908,6 @@ phpdbg_out:
                        efree(SG(request_info).argv);
                }
 
-#ifndef _WIN32
-               /* reset it... else we risk a stack overflow upon next run (when clean'ing) */
-               php_stream_stdio_ops.write = PHPDBG_G(php_stdiop_write);
-#endif
-
-#ifndef ZTS
-               /* force cleanup of auto and core globals */
-               zend_hash_clean(CG(auto_globals));
-               memset( &core_globals, 0, sizeof(php_core_globals));
-#endif
                if (ini_entries) {
                        free(ini_entries);
                }
@@ -1957,42 +1916,70 @@ phpdbg_out:
                        free(ini_override);
                }
 
-               /* this must be forced */
-               CG(unclean_shutdown) = 0;
-
-               /* this is just helpful */
-               PG(report_memleaks) = 0;
+               /* In case we aborted during script execution, we may not reset CG(unclean_shutdown) */
+               if (!(PHPDBG_G(flags) & PHPDBG_IS_RUNNING)) {
+                       CG(unclean_shutdown) = PHPDBG_G(unclean_eval);
+               }
 
                if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) {
                        php_free_shutdown_functions();
                        zend_objects_store_mark_destructed(&EG(objects_store));
                }
 
-               /* sapi_module.deactivate is where to backup things, last chance before mm_shutdown... */
+               /* backup globals when cleaning */
+               if ((cleaning > 0 || remote) && !quit_immediately) {
+                       settings = calloc(1, sizeof(zend_phpdbg_globals));
+
+                       php_phpdbg_globals_ctor(settings);
 
+                       if (PHPDBG_G(exec)) {
+                               settings->exec = zend_strndup(PHPDBG_G(exec), PHPDBG_G(exec_len));
+                               settings->exec_len = PHPDBG_G(exec_len);
+                       }
+                       settings->oplog = PHPDBG_G(oplog);
+                       settings->prompt[0] = PHPDBG_G(prompt)[0];
+                       settings->prompt[1] = PHPDBG_G(prompt)[1];
+                       memcpy(settings->colors, PHPDBG_G(colors), sizeof(settings->colors));
+                       settings->eol = PHPDBG_G(eol);
+                       settings->input_buflen = PHPDBG_G(input_buflen);
+                       memcpy(settings->input_buffer, PHPDBG_G(input_buffer), settings->input_buflen);
+                       settings->flags = PHPDBG_G(flags) & PHPDBG_PRESERVE_FLAGS_MASK;
+               } else {
+                       if (PHPDBG_G(prompt)[0]) {
+                               free(PHPDBG_G(prompt)[0]);
+                       }
+                       if (PHPDBG_G(prompt)[1]) {
+                               free(PHPDBG_G(prompt)[1]);
+                       }
+               }
+
+               /* hack to restore mm_heap->use_custom_heap in order to receive memory leak info */
+               if (use_mm_wrappers) {
+                       /* ASSUMING that mm_heap->use_custom_heap is the first element of the struct ... */
+                       *(int *) mm_heap = 0;
+               }
                zend_try {
                        php_request_shutdown(NULL);
                } zend_end_try();
 
-               if ((PHPDBG_G(flags) & (PHPDBG_IS_QUITTING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_RUNNING) {
+               if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING) && PHPDBG_G(in_execution)) {
                        if (!quit_immediately && !phpdbg_startup_run) {
                                phpdbg_notice("stop", "type=\"normal\"", "Script ended normally");
+                               cleaning++;
                        }
-                       cleaning++;
-               }
-
-               if ((PHPDBG_G(flags) & PHPDBG_IS_STOPPING) == PHPDBG_IS_CLEANING) {
-                       settings = PHPDBG_G(backup);
                }
-
                php_output_deactivate();
 
                zend_try {
                        php_module_shutdown();
                } zend_end_try();
 
-               sapi_shutdown();
+#ifndef _WIN32
+               /* reset it... else we risk a stack overflow upon next run (when clean'ing) */
+               php_stream_stdio_ops.write = PHPDBG_G(php_stdiop_write);
+#endif
 
+               sapi_shutdown();
        }
 
        if ((cleaning > 0 || remote) && !quit_immediately) {
index f900866211735bac9120192ca3f13505e76470ae..d6e8ddb1ce9c0d143704299a611d0afbd047b05c 100644 (file)
@@ -259,6 +259,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
        int bp_count;                                /* breakpoint count */
        int vmret;                                   /* return from last opcode handler execution */
        zend_bool in_execution;                      /* in execution? */
+       zend_bool unclean_eval;                      /* do not check for memory leaks when we needed to bail out during eval */
 
        zend_op_array *(*compile_file)(zend_file_handle *file_handle, int type);
        HashTable file_sources;
@@ -308,8 +309,6 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
        HANDLE sigio_watcher_thread;                 /* sigio watcher thread handle */
        struct win32_sigio_watcher_data swd;
 #endif
-
-       struct _zend_phpdbg_globals *backup;         /* backup of data to store */
 ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */
 
 #endif
index 60c68e2cc35a45f9cdd8f3df87714d553819bccf..7a6a66b50e24da7a2ce748fea876c6c16075da41 100644 (file)
@@ -63,6 +63,7 @@ static void phpdbg_file_breaks_dtor(zval *data) /* {{{ */
        phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) Z_PTR_P(data);
 
        efree((char*)bp->filename);
+       efree(bp);
 } /* }}} */
 
 static void phpdbg_class_breaks_dtor(zval *data) /* {{{ */
@@ -71,11 +72,13 @@ static void phpdbg_class_breaks_dtor(zval *data) /* {{{ */
 
        efree((char*)bp->class_name);
        efree((char*)bp->func_name);
+       efree(bp);
 } /* }}} */
 
 static void phpdbg_opline_class_breaks_dtor(zval *data) /* {{{ */
 {
-       zend_hash_destroy((HashTable *) Z_PTR_P(data));
+       zend_hash_destroy(Z_ARRVAL_P(data));
+       efree(Z_ARRVAL_P(data));
 } /* }}} */
 
 static void phpdbg_opline_breaks_dtor(zval *data) /* {{{ */
@@ -88,6 +91,7 @@ static void phpdbg_opline_breaks_dtor(zval *data) /* {{{ */
        if (bp->func_name) {
                efree((char*)bp->func_name);
        }
+       efree(bp);
 } /* }}} */
 
 PHPDBG_API void phpdbg_reset_breakpoints(void) /* {{{ */
@@ -230,8 +234,9 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
        char realpath[MAXPATHLEN];
        const char *original_path = path;
        zend_bool pending = 0;
+       zend_string *path_str;
 
-       HashTable *broken, *file_breaks =  &PHPDBG_G(bp)[PHPDBG_BREAK_FILE];
+       HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE];
        phpdbg_breakfile_t new_break;
        size_t path_len = 0L;
 
@@ -261,11 +266,13 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
                }
        }
 
-       if (!(broken = zend_hash_str_find_ptr(file_breaks, path, path_len))) {
+       path_str = zend_string_init(path, path_len, 0);
+
+       if (!(broken = zend_hash_find_ptr(file_breaks, path_str))) {
                HashTable breaks;
                zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0);
 
-               broken = zend_hash_str_add_mem(file_breaks, path, path_len, &breaks, sizeof(HashTable));
+               broken = zend_hash_add_mem(file_breaks, path_str, &breaks, sizeof(HashTable));
        }
 
        if (!zend_hash_index_exists(broken, line_num)) {
@@ -278,7 +285,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
                PHPDBG_BREAK_MAPPING(new_break.id, broken);
 
                if (pending) {
-                       zend_string *file, *path_str = zend_string_init(path, path_len, 0);
+                       zend_string *file;
                        ZEND_HASH_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) {
                                HashTable *fileht;
 
@@ -289,7 +296,6 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
                                        break;
                                }
                        } ZEND_HASH_FOREACH_END();
-                       zend_string_release(path_str);
                }
 
                if (pending) {
@@ -304,6 +310,8 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
        } else {
                phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num);
        }
+
+       zend_string_release(path_str);
 } /* }}} */
 
 PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, zend_string *cur, HashTable *fileht) /* {{{ */
@@ -1066,11 +1074,7 @@ static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execut
                zend_try {
                        PHPDBG_G(flags) |= PHPDBG_IN_COND_BP;
                        zend_execute(bp->ops, &retval);
-#if PHP_VERSION_ID >= 50700
                        if (zend_is_true(&retval)) {
-#else
-                       if (zend_is_true(&retval)) {
-#endif
                                breakpoint = SUCCESS;
                        }
                } zend_end_try();
index 12eb3874fde193a10e4e5b6817d3ab108338e4ba..34456bb77bef77e0ebc68376ec010988b8a088cf 100644 (file)
@@ -765,6 +765,9 @@ PHPDBG_API char *phpdbg_read_input(char *buffered) /* {{{ */
                PHPDBG_G(buffer) = estrdup(buffer);
        } else {
                if (PHPDBG_G(buffer)) {
+                       if (buffer) {
+                               efree(buffer);
+                       }
                        buffer = estrdup(PHPDBG_G(buffer));
                }
        }
index 6d5e8949303b4f0f9ad0cf4eded1f6c28f6142ba..bd6718f521340f3cae31ac3d1151e321505ca5c0 100644 (file)
@@ -253,8 +253,8 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
        }
 
 #if HAVE_MMAP
-       if (file->handle.stream.mmap.map) {
-               data.map = file->handle.stream.mmap.map;
+       if (file->type == ZEND_HANDLE_MAPPED) {
+               data.map = file->handle.stream.handle;
        }
 #endif
 
@@ -289,11 +289,13 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) {
        zend_file_handle_dtor(&fake);
 
        dataptr->op_array = ret;
-       if (dataptr->op_array->refcount) {
-               ++*dataptr->op_array->refcount;
-       } else {
-               dataptr->op_array->refcount = emalloc(sizeof(uint32_t));
-               *dataptr->op_array->refcount = 2;
+       if (data->op_array) {
+               if (dataptr->op_array->refcount) {
+                       ++*dataptr->op_array->refcount;
+               } else {
+                       dataptr->op_array->refcount = emalloc(sizeof(uint32_t));
+                       *dataptr->op_array->refcount = 2;
+               }
        }
 
        return ret;
@@ -304,7 +306,7 @@ void phpdbg_free_file_source(zval *zv) {
 
 #if HAVE_MMAP
        if (data->map) {
-               munmap(data->map, data->len + ZEND_MMAP_AHEAD);
+               php_stream_mmap_unmap(data->map);
        } else
 #endif
        if (data->buf) {
index cd9a4acaa0180dc1780fac03013709416b1842df..c771b439d129ab940a114ef26ddf536e31ad378a 100644 (file)
@@ -1281,6 +1281,7 @@ PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) {
                len = phpdbg_mixed_write(fd, buffer, buflen);
        }
 
+       efree(buffer);
        return len;
 }
 
index 5ad3fea79d517583c8f1b4a7994776f45575fbf2..5b5ac2a0750503da8afe0f51c78fe384b997c6a5 100644 (file)
@@ -418,12 +418,13 @@ PHPDBG_COMMAND(exec) /* {{{ */
                                VCWD_CHDIR_FILE(res);
 
                                *SG(request_info).argv = PHPDBG_G(exec);
-                               php_hash_environment();
+                               php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]);
 
                                phpdbg_notice("exec", "type=\"set\" context=\"%s\"", "Set execution context: %s", PHPDBG_G(exec));
 
                                if (PHPDBG_G(in_execution)) {
                                        phpdbg_clean(1);
+                                       return SUCCESS;
                                }
 
                                phpdbg_compile();
@@ -678,7 +679,7 @@ PHPDBG_COMMAND(run) /* {{{ */
                        SG(request_info).argv = erealloc(argv, ++argc * sizeof(char *));
                        SG(request_info).argc = argc;
 
-                       php_hash_environment();
+                       php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]);
                }
 
                zend_try {
@@ -689,13 +690,11 @@ PHPDBG_COMMAND(run) /* {{{ */
                } zend_catch {
                        PHPDBG_G(in_execution) = 0;
 
-                       if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) {
-                               zend_bailout();
-                       }
-
                        if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
                                phpdbg_error("stop", "type=\"bailout\"", "Caught exit/error from VM");
                                restore = 0;
+                       } else {
+                               zend_bailout();
                        }
                } zend_end_try();
 
@@ -708,8 +707,9 @@ PHPDBG_COMMAND(run) /* {{{ */
                        if (EG(exception)) {
                                phpdbg_handle_exception();
                        }
-               }
 
+                       PHPDBG_G(in_execution) = 1;
+               }
                phpdbg_clean(1);
 
                PHPDBG_G(flags) &= ~PHPDBG_IS_RUNNING;
@@ -744,6 +744,7 @@ PHPDBG_COMMAND(ev) /* {{{ */
        zend_execute_data *original_execute_data = EG(current_execute_data);
        zend_class_entry *original_scope = EG(scope);
        zend_vm_stack original_stack = EG(vm_stack);
+       zend_object *ex = NULL;
 
        PHPDBG_OUTPUT_BACKUP();
 
@@ -769,6 +770,7 @@ PHPDBG_COMMAND(ev) /* {{{ */
        zend_try {
                if (zend_eval_stringl(param->str, param->len, &retval, "eval()'d code") == SUCCESS) {
                        if (EG(exception)) {
+                               ex = EG(exception);
                                zend_exception_error(EG(exception), E_ERROR);
                        } else {
                                phpdbg_xml("<eval %r>");
@@ -783,6 +785,10 @@ PHPDBG_COMMAND(ev) /* {{{ */
                        }
                }
        } zend_catch {
+               PHPDBG_G(unclean_eval) = 1;
+               if (ex) {
+                       OBJ_RELEASE(ex);
+               }
                EG(current_execute_data) = original_execute_data;
                EG(scope) = original_scope;
                EG(vm_stack_top) = original_stack->top;
@@ -1185,14 +1191,10 @@ PHPDBG_COMMAND(register) /* {{{ */
 
 PHPDBG_COMMAND(quit) /* {{{ */
 {
-       /* don't allow this to loop, ever ... */
-       if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) {
-               PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
-               PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING);
-               zend_bailout();
-       }
+       PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
+       PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING;
 
-       return PHPDBG_NEXT;
+       return SUCCESS;
 } /* }}} */
 
 PHPDBG_COMMAND(clean) /* {{{ */
@@ -1211,8 +1213,6 @@ PHPDBG_COMMAND(clean) /* {{{ */
        phpdbg_writeln("clean", "constants=\"%d\"", "Constants  %d", zend_hash_num_elements(EG(zend_constants)));
        phpdbg_writeln("clean", "includes=\"%d\"", "Includes   %d", zend_hash_num_elements(&EG(included_files)));
 
-       PHPDBG_G(flags) &= ~PHPDBG_IS_RUNNING;
-
        phpdbg_clean(1);
 
        phpdbg_xml("</cleaninfo>");
@@ -1291,7 +1291,7 @@ int phpdbg_interactive(zend_bool allow_async_unsafe) /* {{{ */
        PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE;
 
        while (ret == SUCCESS || ret == FAILURE) {
-               if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_STOPPING) {
+               if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) {
                        zend_bailout();
                }
 
@@ -1370,15 +1370,14 @@ void phpdbg_clean(zend_bool full) /* {{{ */
 {
        /* this is implicitly required */
        if (PHPDBG_G(ops)) {
-               destroy_op_array(PHPDBG_G(ops));
-               efree(PHPDBG_G(ops));
+               if (destroy_op_array(PHPDBG_G(ops))) {
+                       efree(PHPDBG_G(ops));
+               }
                PHPDBG_G(ops) = NULL;
        }
 
        if (full) {
                PHPDBG_G(flags) |= PHPDBG_IS_CLEANING;
-
-               zend_bailout();
        }
 } /* }}} */
 
index 25c0b4f71fc8f26ce1eb1b26458730153712dfd5..9dda175915eae844a1fca64ffed2f417774790e1 100644 (file)
@@ -64,11 +64,6 @@ PHPDBG_COMMAND(wait); /* }}} */
 /* {{{ prompt commands */
 extern const phpdbg_command_t phpdbg_prompt_commands[]; /* }}} */
 
-/* {{{ */
-#if PHP_VERSION_ID >= 50500
 void phpdbg_execute_ex(zend_execute_data *execute_data);
-#else
-void phpdbg_execute_ex(zend_op_array *op_array);
-#endif /* }}} */
 
 #endif /* PHPDBG_PROMPT_H */
index 2e1e1ed70c49581f21c246d6672e77e2d6854172..4d45066cfa654566bc39cf7fff80cddd9a24416c 100644 (file)
@@ -166,16 +166,20 @@ PHPDBG_API const char *phpdbg_current_file(void) /* {{{ */
 PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname) /* {{{ */
 {
        zend_function *func = NULL;
-       zend_string *lfname = zend_string_alloc(strlen(fname), 0);
-       memcpy(ZSTR_VAL(lfname), zend_str_tolower_dup(fname, ZSTR_LEN(lfname)), ZSTR_LEN(lfname) + 1);
+       zend_string *lfname = zend_string_init(fname, strlen(fname), 0);
+       zend_string *tmp = zend_string_tolower(lfname);
+       zend_string_release(lfname);
+       lfname = tmp;
 
        if (cname) {
                zend_class_entry *ce;
-               zend_string *lcname = zend_string_alloc(strlen(cname), 0);
-               memcpy(ZSTR_VAL(lcname), zend_str_tolower_dup(cname, ZSTR_LEN(lcname)), ZSTR_LEN(lcname) + 1);
+               zend_string *lcname = zend_string_init(cname, strlen(cname), 0);
+               tmp = zend_string_tolower(lcname);
+               zend_string_release(lcname);
+               lcname = tmp;
                ce = zend_lookup_class(lcname);
 
-               efree(lcname);
+               zend_string_release(lcname);
 
                if (ce) {
                        func = zend_hash_find_ptr(&ce->function_table, lfname);
@@ -184,7 +188,7 @@ PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const cha
                func = zend_hash_find_ptr(EG(function_table), lfname);
        }
 
-       efree(lfname);
+       zend_string_release(lfname);
        return func;
 } /* }}} */