From cc70ec1e6735bb60606673c72c5ce9d9cb076e29 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 26 Oct 2014 03:50:28 +0100 Subject: Add question to reset execution in run/exec/clean --- sapi/phpdbg/phpdbg.c | 44 +++++++--------- sapi/phpdbg/phpdbg.h | 7 +-- sapi/phpdbg/phpdbg_cmd.c | 82 ++++++++++------------------- sapi/phpdbg/phpdbg_cmd.h | 1 + sapi/phpdbg/phpdbg_io.c | 49 ++++++++++++++++++ sapi/phpdbg/phpdbg_io.h | 2 + sapi/phpdbg/phpdbg_prompt.c | 123 ++++++++++++++++++++++++-------------------- 7 files changed, 170 insertions(+), 138 deletions(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index aaf1e5f406..ff03c670d0 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -45,6 +45,8 @@ #endif /* }}} */ ZEND_DECLARE_MODULE_GLOBALS(phpdbg); +int phpdbg_startup_run = 0; +char *phpdbg_exec = NULL; static PHP_INI_MH(OnUpdateEol) { @@ -487,7 +489,7 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ case PHPDBG_NEXT: return; } - } while (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); + } while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)); } } else fprintf(stdout, "%s\n", message); @@ -752,7 +754,7 @@ static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */ phpdbg_writeln("intro", "help=\"help\"", "To get help using phpdbg type \"help\" and press enter"); phpdbg_notice("intro", "report=\"%s\"", "Please report bugs to <%s>", PHPDBG_ISSUES); phpdbg_xml(""); - } else { + } else if (phpdbg_startup_run == 0) { if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) { phpdbg_notice(NULL, NULL, "Clean Execution Environment"); } @@ -776,7 +778,7 @@ static inline void phpdbg_sigint_handler(int signo) /* {{{ */ if (PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE) { /* we quit remote consoles on recv SIGINT */ if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { - PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; + PHPDBG_G(flags) |= PHPDBG_IS_STOPPING; zend_bailout(); } } else { @@ -961,8 +963,6 @@ int main(int argc, char **argv) /* {{{ */ zend_ulong zend_extensions_len = 0L; zend_bool ini_ignore; char *ini_override; - char *exec; - size_t exec_len; char *init_file; size_t init_file_len; zend_bool init_file_default; @@ -973,7 +973,6 @@ int main(int argc, char **argv) /* {{{ */ int php_optind, opt, show_banner = 1; long cleaning = 0; zend_bool remote = 0; - int run = 0; int step = 0; #ifdef _WIN32 @@ -1046,8 +1045,6 @@ phpdbg_main: ini_override = NULL; zend_extensions = NULL; zend_extensions_len = 0L; - exec = NULL; - exec_len = 0; init_file = NULL; init_file_len = 0; init_file_default = 1; @@ -1057,14 +1054,13 @@ phpdbg_main: php_optarg = NULL; php_optind = 1; opt = 0; - run = 0; step = 0; sapi_name = NULL; while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (opt) { case 'r': - run++; + phpdbg_startup_run++; break; case 'n': ini_ignore = 1; @@ -1201,14 +1197,12 @@ phpdbg_main: } /* set exec if present on command line */ - if ((argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) - { - exec_len = strlen(argv[php_optind]); - if (exec_len) { - if (exec) { - free(exec); + if (!phpdbg_exec && (argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) { + if (strlen(argv[php_optind])) { + if (phpdbg_exec) { + free(phpdbg_exec); } - exec = strdup(argv[php_optind]); + phpdbg_exec = strdup(argv[php_optind]); } php_optind++; } @@ -1331,7 +1325,7 @@ phpdbg_main: for (i = SG(request_info).argc; --i;) { SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]); } - SG(request_info).argv[i] = exec ? estrndup(exec, exec_len) : estrdup(""); + SG(request_info).argv[i] = phpdbg_exec ? estrdup(phpdbg_exec) : estrdup(""); php_hash_environment(TSRMLS_C); } @@ -1394,11 +1388,12 @@ phpdbg_main: php_stream_stdio_ops.write = phpdbg_stdiop_write; #endif - if (exec) { /* set execution context */ - PHPDBG_G(exec) = phpdbg_resolve_path(exec TSRMLS_CC); + if (phpdbg_exec) { /* set execution context */ + PHPDBG_G(exec) = phpdbg_resolve_path(phpdbg_exec TSRMLS_CC); PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); - free(exec); + free(phpdbg_exec); + phpdbg_exec = NULL; } if (oplog_file) { /* open oplog */ @@ -1448,13 +1443,14 @@ phpdbg_main: PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } - if (run) { + if (phpdbg_startup_run) { /* no need to try{}, run does it ... */ PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC); - if (run > 1) { + if (phpdbg_startup_run > 1) { /* if -r is on the command line more than once just quit */ goto phpdbg_out; } + phpdbg_startup_run = 0; } phpdbg_interact: @@ -1494,7 +1490,7 @@ phpdbg_interact: } } } zend_end_try(); - } while(!cleaning && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); + } while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)); /* this must be forced */ CG(unclean_shutdown) = 0; diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index 8c0dbb4afa..688ba7cdfc 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -187,9 +187,10 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); #define PHPDBG_IN_SIGNAL_HANDLER (1<<30) -#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL|PHPDBG_IN_FINISH|PHPDBG_IN_LEAVE) -#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP) -#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP|PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE) +#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING) #ifndef _WIN32 # define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED) diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c index 30ea48cfbe..ab0755454e 100644 --- a/sapi/phpdbg/phpdbg_cmd.c +++ b/sapi/phpdbg/phpdbg_cmd.c @@ -796,80 +796,30 @@ PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, zend_bool allow_async PHPDBG_API char *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */ { + char buf[PHPDBG_MAX_CMD]; char *cmd = NULL; char *buffer = NULL; - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && (buffered == NULL) && !phpdbg_active_sigsafe_mem(TSRMLS_C)) { fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr); } if (buffered == NULL) { - if (0) { -disconnect: - PHPDBG_G(flags) |= (PHPDBG_IS_QUITTING|PHPDBG_IS_DISCONNECTED); - zend_bailout(); - return NULL; - } - #define USE_LIB_STAR (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)) - /* note: EOF makes readline write prompt again in local console mode - and ignored if compiled without readline */ - /* strongly assuming to be in blocking mode... */ #if USE_LIB_STAR readline: if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) #endif { - char buf[PHPDBG_MAX_CMD]; - int bytes = PHPDBG_G(input_buflen), len = 0; - if (PHPDBG_G(input_buflen)) { - memcpy(buf, PHPDBG_G(input_buffer), bytes); - } - phpdbg_write("prompt", "", "%s", phpdbg_get_prompt(TSRMLS_C)); - PHPDBG_G(last_was_newline) = 1; - - do { - int i; - if (bytes <= 0) { - continue; - } - - for (i = len; i < len + bytes; i++) { - if (buf[i] == '\x03') { - if (i != len + bytes - 1) { - memmove(buf + i, buf + i + 1, len + bytes - i - 1); - } - len--; - i--; - continue; - } - if (buf[i] == '\n') { - PHPDBG_G(input_buflen) = len + bytes - 1 - i; - if (PHPDBG_G(input_buflen)) { - memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen)); - } - if (i != PHPDBG_MAX_CMD - 1) { - buf[i + 1] = 0; - } - cmd = buf; - goto end; - } - } - len += bytes; - /* XXX export the timeout through INI??*/ - } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1 TSRMLS_CC)) > 0); - - if (bytes <= 0) { - goto disconnect; - } - - cmd = buf; + phpdbg_consume_stdin_line(cmd = buf TSRMLS_CC); } #if USE_LIB_STAR else { cmd = readline(phpdbg_get_prompt(TSRMLS_C)); + PHPDBG_G(last_was_newline) = 1; } if (!cmd) { @@ -883,8 +833,7 @@ readline: } else { cmd = buffered; } -end: - PHPDBG_G(last_was_newline) = 1; + buffer = estrdup(cmd); #if USE_LIB_STAR @@ -922,3 +871,24 @@ PHPDBG_API void phpdbg_destroy_input(char **input TSRMLS_DC) /*{{{ */ { efree(*input); } /* }}} */ + +PHPDBG_API int phpdbg_ask_user_permission(const char *question TSRMLS_DC) { + if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) { + char buf[PHPDBG_MAX_CMD]; + phpdbg_out("%s", question); + phpdbg_out(" (type y or n): "); + + while (1) { + phpdbg_consume_stdin_line(buf TSRMLS_CC); + if (buf[1] == '\n' && (buf[0] == 'y' || buf[0] == 'n')) { + if (buf[0] == 'y') { + return SUCCESS; + } + return FAILURE; + } + phpdbg_out("Please enter either y (yes) or n (no): "); + } + } + + return SUCCESS; +} diff --git a/sapi/phpdbg/phpdbg_cmd.h b/sapi/phpdbg/phpdbg_cmd.h index 3896551c9a..4c9e5383d8 100644 --- a/sapi/phpdbg/phpdbg_cmd.h +++ b/sapi/phpdbg/phpdbg_cmd.h @@ -131,6 +131,7 @@ typedef struct { */ PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC); PHPDBG_API void phpdbg_destroy_input(char** TSRMLS_DC); +PHPDBG_API int phpdbg_ask_user_permission(const char *question TSRMLS_DC); /** * Stack Management diff --git a/sapi/phpdbg/phpdbg_io.c b/sapi/phpdbg/phpdbg_io.c index 97f0356285..a2a5c5969f 100644 --- a/sapi/phpdbg/phpdbg_io.c +++ b/sapi/phpdbg/phpdbg_io.c @@ -47,6 +47,55 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +/* is easy to generalize ... but not needed for now */ +PHPDBG_API int phpdbg_consume_stdin_line(char *buf TSRMLS_DC) { + int bytes = PHPDBG_G(input_buflen), len = 0; + + if (PHPDBG_G(input_buflen)) { + memcpy(buf, PHPDBG_G(input_buffer), bytes); + } + + PHPDBG_G(last_was_newline) = 1; + + do { + int i; + if (bytes <= 0) { + continue; + } + + for (i = len; i < len + bytes; i++) { + if (buf[i] == '\x03') { + if (i != len + bytes - 1) { + memmove(buf + i, buf + i + 1, len + bytes - i - 1); + } + len--; + i--; + continue; + } + if (buf[i] == '\n') { + PHPDBG_G(input_buflen) = len + bytes - 1 - i; + if (PHPDBG_G(input_buflen)) { + memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen)); + } + if (i != PHPDBG_MAX_CMD - 1) { + buf[i + 1] = 0; + } + return i; + } + } + + len += bytes; + } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1 TSRMLS_CC)) > 0); + + if (bytes <= 0) { + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED; + zend_bailout(); + return 0; + } + + return bytes; +} + PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo TSRMLS_DC) { int got_now, i = len, j; char *p = ptr; diff --git a/sapi/phpdbg/phpdbg_io.h b/sapi/phpdbg/phpdbg_io.h index 3ac8f4112d..a5659e88c6 100644 --- a/sapi/phpdbg/phpdbg_io.h +++ b/sapi/phpdbg/phpdbg_io.h @@ -21,6 +21,8 @@ #include "phpdbg.h" +PHPDBG_API int phpdbg_consume_stdin_line(char *buf TSRMLS_DC); + PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo TSRMLS_DC); PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len); PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo TSRMLS_DC); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 2e0c698f05..29c75c583c 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -43,6 +43,8 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); ZEND_EXTERN_MODULE_GLOBALS(output); +extern int phpdbg_startup_run; +extern char *phpdbg_exec; #ifdef HAVE_LIBDL #ifdef PHP_WIN32 @@ -355,6 +357,11 @@ PHPDBG_COMMAND(exec) /* {{{ */ size_t res_len = strlen(res); if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) { + if (EG(in_execution)) { + if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?" TSRMLS_CC) == FAILURE) { + return FAILURE; + } + } if (PHPDBG_G(exec)) { phpdbg_notice("exec", "type=\"unset\" context=\"%s\"", "Unsetting old execution context: %s", PHPDBG_G(exec)); @@ -378,9 +385,11 @@ PHPDBG_COMMAND(exec) /* {{{ */ phpdbg_notice("exec", "type=\"set\" context=\"%s\"", "Set execution context: %s", PHPDBG_G(exec)); - if (phpdbg_compile(TSRMLS_C) == FAILURE) { - phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s", PHPDBG_G(exec)); + if (EG(in_execution)) { + phpdbg_clean(1 TSRMLS_CC); } + + phpdbg_compile(TSRMLS_C); } else { phpdbg_notice("exec", "type=\"unchanged\"", "Execution context not changed"); } @@ -399,20 +408,15 @@ int phpdbg_compile(TSRMLS_D) /* {{{ */ if (!PHPDBG_G(exec)) { phpdbg_error("inactive", "type=\"nocontext\"", "No execution context"); - return SUCCESS; - } - - if (EG(in_execution)) { - phpdbg_error("inactive", "type=\"isrunning\"", "Cannot compile while in execution"); return FAILURE; } if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC) == SUCCESS) { - PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE TSRMLS_CC); zend_destroy_file_handle(&fh TSRMLS_CC); phpdbg_notice("compile", "context=\"%s\"", "Successful compilation of %s", PHPDBG_G(exec)); + return SUCCESS; } else { phpdbg_error("compile", "type=\"openfailure\" context=\"%s\"", "Could not open file %s", PHPDBG_G(exec)); @@ -570,11 +574,6 @@ static inline void phpdbg_handle_exception(TSRMLS_D) /* }}} */ PHPDBG_COMMAND(run) /* {{{ */ { - if (EG(in_execution)) { - phpdbg_error("inactive", "type=\"isrunning\"", "Cannot start another execution while one is in progress"); - return SUCCESS; - } - if (PHPDBG_G(ops) || PHPDBG_G(exec)) { zend_op **orig_opline = EG(opline_ptr); zend_op_array *orig_op_array = EG(active_op_array); @@ -582,6 +581,14 @@ PHPDBG_COMMAND(run) /* {{{ */ zend_bool restore = 1; zend_execute_data *ex = EG(current_execute_data); + if (EG(in_execution)) { + if (phpdbg_ask_user_permission("Do you really want to restart execution?" TSRMLS_CC) == SUCCESS) { + phpdbg_startup_run++; + phpdbg_clean(1 TSRMLS_CC); + } + return SUCCESS; + } + if (!PHPDBG_G(ops)) { if (phpdbg_compile(TSRMLS_C) == FAILURE) { phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s, cannot run", PHPDBG_G(exec)); @@ -643,7 +650,7 @@ PHPDBG_COMMAND(run) /* {{{ */ EG(opline_ptr) = orig_opline; EG(return_value_ptr_ptr) = orig_retval_ptr; - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { phpdbg_error("stop", "type=\"bailout\"", "Caught exit/error from VM"); restore = 0; } @@ -1127,7 +1134,7 @@ PHPDBG_COMMAND(register) /* {{{ */ PHPDBG_COMMAND(quit) /* {{{ */ { /* don't allow this to loop, ever ... */ - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; zend_bailout(); } @@ -1138,8 +1145,9 @@ PHPDBG_COMMAND(quit) /* {{{ */ PHPDBG_COMMAND(clean) /* {{{ */ { if (EG(in_execution)) { - phpdbg_error("inactive", "type=\"isrunning\"", "Cannot clean environment while executing"); - return SUCCESS; + if (phpdbg_ask_user_permission("Do you really want to clean your current environment?" TSRMLS_CC) == FAILURE) { + return SUCCESS; + } } phpdbg_out("Cleaning Execution Environment\n"); @@ -1227,60 +1235,64 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */ PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; - input = phpdbg_read_input(NULL TSRMLS_CC); + while (1) { + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); + } - if (input) { - do { - phpdbg_init_param(&stack, STACK_PARAM); + if (!(input = phpdbg_read_input(NULL TSRMLS_CC))) { + break; + } - if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) { - phpdbg_activate_err_buf(1 TSRMLS_CC); + + phpdbg_init_param(&stack, STACK_PARAM); + + if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) { + phpdbg_activate_err_buf(1 TSRMLS_CC); #ifdef PHP_WIN32 #define PARA ((phpdbg_param_t *)stack.next)->type - if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { - sigio_watcher_start(); - } + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { + sigio_watcher_start(); + } #endif - switch (ret = phpdbg_stack_execute(&stack, allow_async_unsafe TSRMLS_CC)) { - case FAILURE: - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - if (!allow_async_unsafe || phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) { - phpdbg_output_err_buf(NULL, "%b", "%b" TSRMLS_CC); - } + switch (ret = phpdbg_stack_execute(&stack, allow_async_unsafe TSRMLS_CC)) { + case FAILURE: + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { + if (!allow_async_unsafe || phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) { + phpdbg_output_err_buf(NULL, "%b", "%b" TSRMLS_CC); } - break; + } + break; - case PHPDBG_LEAVE: - case PHPDBG_FINISH: - case PHPDBG_UNTIL: - case PHPDBG_NEXT: { - phpdbg_activate_err_buf(0 TSRMLS_CC); - phpdbg_free_err_buf(TSRMLS_C); - if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - phpdbg_error("command", "type=\"noexec\"", "Not running"); - } - goto out; + case PHPDBG_LEAVE: + case PHPDBG_FINISH: + case PHPDBG_UNTIL: + case PHPDBG_NEXT: { + phpdbg_activate_err_buf(0 TSRMLS_CC); + phpdbg_free_err_buf(TSRMLS_C); + if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { + phpdbg_error("command", "type=\"noexec\"", "Not running"); } + break; } + } - phpdbg_activate_err_buf(0 TSRMLS_CC); - phpdbg_free_err_buf(TSRMLS_C); + phpdbg_activate_err_buf(0 TSRMLS_CC); + phpdbg_free_err_buf(TSRMLS_C); #ifdef PHP_WIN32 - if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { - sigio_watcher_stop(); - } + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { + sigio_watcher_stop(); + } #undef PARA #endif - } + } - phpdbg_stack_free(&stack); - phpdbg_destroy_input(&input TSRMLS_CC); - PHPDBG_G(req_id) = 0; - } while ((input = phpdbg_read_input(NULL TSRMLS_CC))); + phpdbg_stack_free(&stack); + phpdbg_destroy_input(&input TSRMLS_CC); + PHPDBG_G(req_id) = 0; } -out: if (input) { phpdbg_stack_free(&stack); phpdbg_destroy_input(&input TSRMLS_CC); @@ -1308,6 +1320,7 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ } if (full) { + phpdbg_exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */ PHPDBG_G(flags) |= PHPDBG_IS_CLEANING; zend_bailout(); @@ -1593,7 +1606,7 @@ void phpdbg_force_interruption(TSRMLS_D) { next: PHPDBG_G(flags) &= ~PHPDBG_IN_SIGNAL_HANDLER; - if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) { + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { zend_bailout(); } } -- cgit v1.2.1 From 51c1cc4ff5a1ae1606d07de79db07d9d826378cf Mon Sep 17 00:00:00 2001 From: krakjoe Date: Sun, 26 Oct 2014 07:08:29 +0000 Subject: disable output buffering by default --- sapi/phpdbg/phpdbg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index ff03c670d0..f8879d77ab 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -730,7 +730,8 @@ const char phpdbg_ini_hardcoded[] = "log_errors=On\n" "max_execution_time=0\n" "max_input_time=-1\n" -"error_log=\n\0"; +"error_log=\n" +"output_buffering=off\0"; /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */ #define INI_DEFAULT(name, value) \ -- cgit v1.2.1 From 41537cdddc71a6e499f1c7c118bf862105ff95fa Mon Sep 17 00:00:00 2001 From: krakjoe Date: Sun, 26 Oct 2014 07:24:35 +0000 Subject: remove dodgy param parser, bring userland breakpoint api inline with PHP7 --- sapi/phpdbg/phpdbg.c | 85 +++++++--- sapi/phpdbg/phpdbg_cmd.c | 73 -------- sapi/phpdbg/phpdbg_cmd.h | 1 - sapi/phpdbg/phpdbg_parser.c | 396 ++++++++++++++++++++------------------------ sapi/phpdbg/phpdbg_parser.h | 39 +++-- 5 files changed, 278 insertions(+), 316 deletions(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index f8879d77ab..493d8ec20c 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -301,24 +301,12 @@ static PHP_FUNCTION(phpdbg_exec) } } /* }}} */ -/* {{{ proto void phpdbg_break([integer type, string expression]) +/* {{{ proto void phpdbg_break_next() instructs phpdbg to insert a breakpoint at the next opcode */ -static PHP_FUNCTION(phpdbg_break) +static PHP_FUNCTION(phpdbg_break_next) { - if (ZEND_NUM_ARGS() > 0) { - long type = 0; - char *expr = NULL; - int expr_len = 0; - phpdbg_param_t param; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &type, &expr, &expr_len) == FAILURE) { - return; - } - - phpdbg_parse_param(expr, expr_len, ¶m TSRMLS_CC); - phpdbg_do_break(¶m TSRMLS_CC); - phpdbg_clear_param(¶m TSRMLS_CC); - + if (zend_parse_parameters_none() != SUCCESS) { + return; } else if (EG(current_execute_data) && EG(active_op_array)) { zend_ulong opline_num = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); @@ -328,6 +316,48 @@ static PHP_FUNCTION(phpdbg_break) } } /* }}} */ +/* {{{ proto void phpdbg_break_file(string file, integer line) */ +static PHP_FUNCTION(phpdbg_break_file) +{ + char *file = NULL; + int flen = 0; + long line; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &file, &flen, &line) == FAILURE) { + return; + } + + phpdbg_set_breakpoint_file(file, line TSRMLS_CC); +} /* }}} */ + +/* {{{ proto void phpdbg_break_method(string class, string method) */ +static PHP_FUNCTION(phpdbg_break_method) +{ + char *class = NULL, + *method = NULL; + int clen = 0, + mlen = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &class, &clen, &method, &mlen) == FAILURE) { + return; + } + + phpdbg_set_breakpoint_method(class, method TSRMLS_CC); +} /* }}} */ + +/* {{{ proto void phpdbg_break_function(string function) */ +static PHP_FUNCTION(phpdbg_break_function) +{ + char *function = NULL; + int function_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &function, &function_len) == FAILURE) { + return; + } + + phpdbg_set_breakpoint_symbol(function, function_len TSRMLS_CC); +} /* }}} */ + /* {{{ proto void phpdbg_clear(void) instructs phpdbg to clear breakpoints */ static PHP_FUNCTION(phpdbg_clear) @@ -377,9 +407,21 @@ static PHP_FUNCTION(phpdbg_prompt) phpdbg_set_prompt(prompt TSRMLS_CC); } /* }}} */ -ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_arginfo, 0, 0, 0) - ZEND_ARG_INFO(0, type) - ZEND_ARG_INFO(0, expression) +ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_next_arginfo, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_file_arginfo, 0, 0, 2) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, line) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_method_arginfo, 0, 0, 2) + ZEND_ARG_INFO(0, class) + ZEND_ARG_INFO(0, method) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_function_arginfo, 0, 0, 1) + ZEND_ARG_INFO(0, function) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_color_arginfo, 0, 0, 0) @@ -400,7 +442,10 @@ ZEND_END_ARG_INFO() zend_function_entry phpdbg_user_functions[] = { PHP_FE(phpdbg_clear, phpdbg_clear_arginfo) - PHP_FE(phpdbg_break, phpdbg_break_arginfo) + PHP_FE(phpdbg_break_next, phpdbg_break_next_arginfo) + PHP_FE(phpdbg_break_file, phpdbg_break_file_arginfo) + PHP_FE(phpdbg_break_method, phpdbg_break_method_arginfo) + PHP_FE(phpdbg_break_function, phpdbg_break_function_arginfo) PHP_FE(phpdbg_exec, phpdbg_exec_arginfo) PHP_FE(phpdbg_color, phpdbg_color_arginfo) PHP_FE(phpdbg_prompt, phpdbg_prompt_arginfo) diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c index ab0755454e..13d5a0d634 100644 --- a/sapi/phpdbg/phpdbg_cmd.c +++ b/sapi/phpdbg/phpdbg_cmd.c @@ -70,79 +70,6 @@ PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param TSRMLS_ } } -PHPDBG_API phpdbg_param_type phpdbg_parse_param(const char *str, size_t len, phpdbg_param_t *param TSRMLS_DC) /* {{{ */ -{ - char *class_name, *func_name; - - if (len == 0) { - param->type = EMPTY_PARAM; - goto parsed; - } - - if (phpdbg_is_addr(str)) { - param->addr = strtoul(str, 0, 16); - param->type = ADDR_PARAM; - goto parsed; - - } else if (phpdbg_is_numeric(str)) { - param->num = strtol(str, NULL, 0); - param->type = NUMERIC_PARAM; - goto parsed; - - } else if (phpdbg_is_class_method(str, len+1, &class_name, &func_name)) { - param->method.class = class_name; - param->method.name = func_name; - param->type = METHOD_PARAM; - goto parsed; - } else { - char *line_pos = strrchr(str, ':'); - - if (line_pos && phpdbg_is_numeric(line_pos+1)) { - if (strchr(str, ':') == line_pos) { - char path[MAXPATHLEN]; - - memcpy(path, str, line_pos - str); - path[line_pos - str] = 0; - *line_pos = 0; - param->file.name = phpdbg_resolve_path(path TSRMLS_CC); - param->file.line = strtol(line_pos+1, NULL, 0); - param->type = FILE_PARAM; - - goto parsed; - } - } - - line_pos = strrchr(str, '#'); - - if (line_pos && phpdbg_is_numeric(line_pos+1)) { - if (strchr(str, '#') == line_pos) { - param->num = strtol(line_pos + 1, NULL, 0); - - if (phpdbg_is_class_method(str, line_pos - str, &class_name, &func_name)) { - param->method.class = class_name; - param->method.name = func_name; - param->type = NUMERIC_METHOD_PARAM; - } else { - param->len = line_pos - str; - param->str = estrndup(str, param->len); - param->type = NUMERIC_FUNCTION_PARAM; - } - - goto parsed; - } - } - } - - param->str = estrndup(str, len); - param->len = len; - param->type = STR_PARAM; - -parsed: - phpdbg_debug("phpdbg_parse_param(\"%s\", %lu): %s", - str, len, phpdbg_get_param_type(param TSRMLS_CC)); - return param->type; -} /* }}} */ - PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param TSRMLS_DC) /* {{{ */ { if (param) { diff --git a/sapi/phpdbg/phpdbg_cmd.h b/sapi/phpdbg/phpdbg_cmd.h index 4c9e5383d8..a79641c080 100644 --- a/sapi/phpdbg/phpdbg_cmd.h +++ b/sapi/phpdbg/phpdbg_cmd.h @@ -145,7 +145,6 @@ PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack); /* * Parameter Management */ -PHPDBG_API phpdbg_param_type phpdbg_parse_param(const char*, size_t, phpdbg_param_t* TSRMLS_DC); PHPDBG_API void phpdbg_clear_param(phpdbg_param_t* TSRMLS_DC); PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t*, phpdbg_param_t* TSRMLS_DC); PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *, const phpdbg_param_t * TSRMLS_DC); diff --git a/sapi/phpdbg/phpdbg_parser.c b/sapi/phpdbg/phpdbg_parser.c index c766868369..433423db87 100644 --- a/sapi/phpdbg/phpdbg_parser.c +++ b/sapi/phpdbg/phpdbg_parser.c @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.7" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse phpdbg_parse @@ -70,11 +68,9 @@ #define yydebug phpdbg_debug #define yynerrs phpdbg_nerrs - /* Copy the first part of user declarations. */ - -/* Line 268 of yacc.c */ -#line 1 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 371 of yacc.c */ +#line 1 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" /* @@ -101,14 +97,16 @@ static int yyerror(void ***tsrm_ls, const char *msg); ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +/* Line 371 of yacc.c */ +#line 102 "sapi/phpdbg/phpdbg_parser.c" -/* Line 268 of yacc.c */ -#line 107 "sapi/phpdbg/phpdbg_parser.c" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -118,15 +116,20 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); # define YYERROR_VERBOSE 1 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "phpdbg_parser.h". */ +#ifndef YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED +# define YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int phpdbg_debug; #endif - /* "%code requires" blocks. */ - -/* Line 288 of yacc.c */ -#line 31 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 387 of yacc.c */ +#line 31 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -135,9 +138,8 @@ typedef void* yyscan_t; #endif - -/* Line 288 of yacc.c */ -#line 141 "sapi/phpdbg/phpdbg_parser.c" +/* Line 387 of yacc.c */ +#line 143 "sapi/phpdbg/phpdbg_parser.c" /* Tokens. */ #ifndef YYTOKENTYPE @@ -189,7 +191,6 @@ typedef void* yyscan_t; - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -198,11 +199,26 @@ typedef int YYSTYPE; #endif -/* Copy the second part of user declarations. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *YYPARSE_PARAM); +#else +int phpdbg_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *tsrm_ls); +#else +int phpdbg_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED */ +/* Copy the second part of user declarations. */ -/* Line 343 of yacc.c */ -#line 206 "sapi/phpdbg/phpdbg_parser.c" +/* Line 390 of yacc.c */ +#line 222 "sapi/phpdbg/phpdbg_parser.c" #ifdef short # undef short @@ -255,24 +271,24 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -308,6 +324,7 @@ YYID (yyi) # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -399,20 +416,20 @@ union yyalloc #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ while (YYID (0)) # endif # endif @@ -505,7 +522,7 @@ static const yytype_uint8 yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -519,7 +536,7 @@ static const char *const yytname[] = "\"opcode\"", "\"identifier (command or function name)\"", "\"input (input string or data)\"", "\"input\"", "\"request id (-r %d)\"", "$accept", "input", "parameters", "parameter", - "req_id", "full_expression", 0 + "req_id", "full_expression", YY_NULL }; #endif @@ -599,10 +616,10 @@ static const yytype_uint8 yytable[] = 32, 36, 39, 40, 0, 0, 41, 42, 27 }; -#define yypact_value_is_default(yystate) \ - ((yystate) == (-16)) +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-16))) -#define yytable_value_is_error(yytable_value) \ +#define yytable_value_is_error(Yytable_value) \ YYID (0) static const yytype_int8 yycheck[] = @@ -652,62 +669,35 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (tsrm_ls, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - /* This macro is provided for backward compatibility. */ - #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else @@ -758,6 +748,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls) void *tsrm_ls; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; YYUSE (tsrm_ls); @@ -770,7 +762,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls) switch (yytype) { default: - break; + break; } } @@ -1012,12 +1004,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULL; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1077,11 +1068,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } } } @@ -1101,10 +1094,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, # undef YYCASE_ } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } if (*yymsg_alloc < yysize) { @@ -1166,25 +1161,11 @@ yydestruct (yymsg, yytype, yyvaluep, tsrm_ls) { default: - break; + break; } } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void *tsrm_ls); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /*----------. @@ -1216,8 +1197,31 @@ yyparse (tsrm_ls) /* The lookahead symbol. */ int yychar; + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +static YYSTYPE yyval_default; +# define YY_INITIAL_VALUE(Value) = Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1230,7 +1234,7 @@ YYSTYPE yylval; `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1248,7 +1252,7 @@ YYSTYPE yylval; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1266,9 +1270,8 @@ YYSTYPE yylval; Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1277,14 +1280,6 @@ YYSTYPE yylval; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1425,7 +1420,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1462,37 +1459,32 @@ yyreduce: switch (yyn) { case 3: - -/* Line 1806 of yacc.c */ -#line 68 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 68 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } break; case 5: - -/* Line 1806 of yacc.c */ -#line 73 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 73 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } break; case 6: - -/* Line 1806 of yacc.c */ -#line 74 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 74 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(2) - (2)])); } break; case 7: - -/* Line 1806 of yacc.c */ -#line 75 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 75 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (2)]); } break; case 8: - -/* Line 1806 of yacc.c */ -#line 79 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 79 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = FILE_PARAM; (yyval).file.name = (yyvsp[(2) - (3)]).str; @@ -1501,9 +1493,8 @@ yyreduce: break; case 9: - -/* Line 1806 of yacc.c */ -#line 84 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 84 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = (yyvsp[(1) - (4)]).str; @@ -1512,9 +1503,8 @@ yyreduce: break; case 10: - -/* Line 1806 of yacc.c */ -#line 89 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 89 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (4)]).len + (yyvsp[(2) - (4)]).len + 1); @@ -1528,9 +1518,8 @@ yyreduce: break; case 11: - -/* Line 1806 of yacc.c */ -#line 99 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 99 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (5)]).len + (yyvsp[(2) - (5)]).len + 1); @@ -1544,9 +1533,8 @@ yyreduce: break; case 12: - -/* Line 1806 of yacc.c */ -#line 109 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 109 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (3)]).str; @@ -1555,9 +1543,8 @@ yyreduce: break; case 13: - -/* Line 1806 of yacc.c */ -#line 114 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 114 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (5)]).str; @@ -1567,9 +1554,8 @@ yyreduce: break; case 14: - -/* Line 1806 of yacc.c */ -#line 120 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 120 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FUNCTION_PARAM; (yyval).str = (yyvsp[(1) - (3)]).str; @@ -1579,9 +1565,8 @@ yyreduce: break; case 15: - -/* Line 1806 of yacc.c */ -#line 126 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 126 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = COND_PARAM; (yyval).str = (yyvsp[(2) - (2)]).str; @@ -1590,65 +1575,56 @@ yyreduce: break; case 16: - -/* Line 1806 of yacc.c */ -#line 131 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 131 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 17: - -/* Line 1806 of yacc.c */ -#line 132 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 132 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 18: - -/* Line 1806 of yacc.c */ -#line 133 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 133 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 19: - -/* Line 1806 of yacc.c */ -#line 134 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 134 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 20: - -/* Line 1806 of yacc.c */ -#line 135 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 135 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 21: - -/* Line 1806 of yacc.c */ -#line 136 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 136 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 22: - -/* Line 1806 of yacc.c */ -#line 137 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 137 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 23: - -/* Line 1806 of yacc.c */ -#line 141 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 141 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { PHPDBG_G(req_id) = (yyvsp[(1) - (1)]).num; } break; case 25: - -/* Line 1806 of yacc.c */ -#line 146 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 146 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = EVAL_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1657,9 +1633,8 @@ yyreduce: break; case 26: - -/* Line 1806 of yacc.c */ -#line 151 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 151 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = SHELL_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1668,9 +1643,8 @@ yyreduce: break; case 27: - -/* Line 1806 of yacc.c */ -#line 156 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 156 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = RUN_PARAM; (yyval).len = 0; @@ -1678,9 +1652,8 @@ yyreduce: break; case 28: - -/* Line 1806 of yacc.c */ -#line 160 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 1792 of yacc.c */ +#line 160 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" { (yyval).type = RUN_PARAM; (yyval).str = (yyvsp[(3) - (3)]).str; @@ -1689,9 +1662,8 @@ yyreduce: break; - -/* Line 1806 of yacc.c */ -#line 1695 "sapi/phpdbg/phpdbg_parser.c" +/* Line 1792 of yacc.c */ +#line 1667 "sapi/phpdbg/phpdbg_parser.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1854,7 +1826,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -1878,7 +1852,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -1920,9 +1894,8 @@ yyreturn: } - -/* Line 2067 of yacc.c */ -#line 167 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 2055 of yacc.c */ +#line 167 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" static int yyerror(void ***tsrm_ls, const char *msg) { @@ -1948,4 +1921,3 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC) { return yyparse(NULL); #endif } - diff --git a/sapi/phpdbg/phpdbg_parser.h b/sapi/phpdbg/phpdbg_parser.h index dfa155d718..4cd8ed6d00 100644 --- a/sapi/phpdbg/phpdbg_parser.h +++ b/sapi/phpdbg/phpdbg_parser.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,10 +30,18 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED +# define YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int phpdbg_debug; +#endif /* "%code requires" blocks. */ - -/* Line 2068 of yacc.c */ -#line 31 "/root/php-src-xml-data-phpdbg/sapi/phpdbg/phpdbg_parser.y" +/* Line 2058 of yacc.c */ +#line 31 "/usr/src/php-src/sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -42,9 +50,8 @@ typedef void* yyscan_t; #endif - -/* Line 2068 of yacc.c */ -#line 48 "sapi/phpdbg/phpdbg_parser.h" +/* Line 2058 of yacc.c */ +#line 55 "sapi/phpdbg/phpdbg_parser.h" /* Tokens. */ #ifndef YYTOKENTYPE @@ -96,7 +103,6 @@ typedef void* yyscan_t; - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 @@ -105,5 +111,18 @@ typedef int YYSTYPE; #endif +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *YYPARSE_PARAM); +#else +int phpdbg_parse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int phpdbg_parse (void *tsrm_ls); +#else +int phpdbg_parse (); +#endif +#endif /* ! YYPARSE_PARAM */ - +#endif /* !YY_PHPDBG_SAPI_PHPDBG_PHPDBG_PARSER_H_INCLUDED */ -- cgit v1.2.1 From 69bc61de419ccd92bfa308f356b56591f7696413 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 26 Oct 2014 10:48:45 +0100 Subject: Fix nullptr dereference in clean without exec context --- sapi/phpdbg/phpdbg_prompt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 29c75c583c..eca4c6ac2b 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1320,7 +1320,10 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ } if (full) { - phpdbg_exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */ + if (PHPDBG_G(exec)) { + phpdbg_exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */ + } + PHPDBG_G(flags) |= PHPDBG_IS_CLEANING; zend_bailout(); -- cgit v1.2.1 From 3ab7734b88f1842b818526e2e3f34022c3270057 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 26 Oct 2014 20:43:49 +0100 Subject: Stabilize execution, always run destructors and extended file breakpoints --- sapi/phpdbg/phpdbg.c | 104 +++++++++++++++++++++++-------- sapi/phpdbg/phpdbg.h | 92 +++++++++++++-------------- sapi/phpdbg/phpdbg_bp.c | 148 +++++++++++++++++++++++++++++++++++--------- sapi/phpdbg/phpdbg_bp.h | 26 ++++---- sapi/phpdbg/phpdbg_cmd.c | 2 +- sapi/phpdbg/phpdbg_list.c | 2 + sapi/phpdbg/phpdbg_out.c | 2 + sapi/phpdbg/phpdbg_prompt.c | 21 +++---- 8 files changed, 268 insertions(+), 129 deletions(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 493d8ec20c..3e31f76898 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -46,7 +46,6 @@ ZEND_DECLARE_MODULE_GLOBALS(phpdbg); int phpdbg_startup_run = 0; -char *phpdbg_exec = NULL; static PHP_INI_MH(OnUpdateEol) { @@ -186,7 +185,8 @@ static void php_phpdbg_destroy_registered(void *data) /* {{{ */ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], 8, NULL, php_phpdbg_destroy_bp_file, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); @@ -216,8 +216,8 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); zend_hash_destroy(&PHPDBG_G(seek)); - zend_hash_destroy(&PHPDBG_G(registered)); zend_hash_destroy(&PHPDBG_G(file_sources)); + zend_hash_destroy(&PHPDBG_G(registered)); zend_hash_destroy(&PHPDBG_G(watchpoints)); zend_llist_destroy(&PHPDBG_G(watchlist_mem)); @@ -363,6 +363,7 @@ static PHP_FUNCTION(phpdbg_break_function) static PHP_FUNCTION(phpdbg_clear) { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -543,11 +544,27 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */ { + if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + zend_phpdbg_globals *pg = PHPDBG_G(backup) = calloc(1, sizeof(zend_phpdbg_globals)); + + php_phpdbg_globals_ctor(pg); + + pg->exec = 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]; + memset(pg->colors, PHPDBG_G(colors), sizeof(pg->colors)); + pg->eol = PHPDBG_G(eol); + pg->flags = PHPDBG_G(flags) & PHPDBG_PRESERVE_FLAGS_MASK; + } + fflush(stdout); if(SG(request_info).argv0) { free(SG(request_info).argv0); SG(request_info).argv0 = NULL; } + return SUCCESS; } /* }}} */ @@ -1009,6 +1026,7 @@ int main(int argc, char **argv) /* {{{ */ zend_ulong zend_extensions_len = 0L; zend_bool ini_ignore; char *ini_override; + char *exec = NULL; char *init_file; size_t init_file_len; zend_bool init_file_default; @@ -1020,6 +1038,7 @@ int main(int argc, char **argv) /* {{{ */ long cleaning = 0; zend_bool remote = 0; int step = 0; + zend_phpdbg_globals *settings = NULL; #ifdef _WIN32 char *bp_tmp_file = NULL; @@ -1102,6 +1121,9 @@ phpdbg_main: opt = 0; step = 0; sapi_name = NULL; + if (settings) { + exec = settings->exec; + } while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (opt) { @@ -1243,12 +1265,12 @@ phpdbg_main: } /* set exec if present on command line */ - if (!phpdbg_exec && (argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) { + if (!exec && (argc > php_optind) && (strcmp(argv[php_optind-1], "--") != SUCCESS)) { if (strlen(argv[php_optind])) { - if (phpdbg_exec) { - free(phpdbg_exec); + if (exec) { + free(exec); } - phpdbg_exec = strdup(argv[php_optind]); + exec = strdup(argv[php_optind]); } php_optind++; } @@ -1309,20 +1331,31 @@ phpdbg_main: #endif zend_mm_heap *mm_heap; - /* setup remote server if necessary */ - if (!cleaning && listen > 0) { - server = phpdbg_open_socket(address, listen TSRMLS_CC); - if (-1 > server || phpdbg_remote_init(address, listen, server, &socket, &stream TSRMLS_CC) == FAILURE) { - exit(0); + /* set flags from command line */ + PHPDBG_G(flags) = flags; + + if (settings) { +#ifdef ZTS + *((zend_phpdbg_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(phpdbg_globals_id)]) = *settings; +#else + phpdbg_globals = *settings; +#endif } + /* setup remote server if necessary */ + if (!cleaning && listen > 0) { + server = phpdbg_open_socket(address, listen TSRMLS_CC); + if (-1 > server || phpdbg_remote_init(address, listen, server, &socket, &stream TSRMLS_CC) == FAILURE) { + exit(0); + } + #ifndef _WIN32 - sigaction(SIGIO, &sigio_struct, NULL); + sigaction(SIGIO, &sigio_struct, NULL); #endif - /* set remote flag to stop service shutting down upon quit */ - remote = 1; - } + /* set remote flag to stop service shutting down upon quit */ + remote = 1; + } mm_heap = phpdbg_mm_get_heap(); @@ -1371,7 +1404,7 @@ phpdbg_main: for (i = SG(request_info).argc; --i;) { SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]); } - SG(request_info).argv[i] = phpdbg_exec ? estrdup(phpdbg_exec) : estrdup(""); + SG(request_info).argv[i] = exec ? estrdup(exec) : estrdup(""); php_hash_environment(TSRMLS_C); } @@ -1392,9 +1425,6 @@ phpdbg_main: PG(modules_activated) = 0; - /* set flags from command line */ - PHPDBG_G(flags) = flags; - /* setup io here */ if (remote) { PHPDBG_G(flags) |= PHPDBG_IS_REMOTE; @@ -1434,12 +1464,12 @@ phpdbg_main: php_stream_stdio_ops.write = phpdbg_stdiop_write; #endif - if (phpdbg_exec) { /* set execution context */ - PHPDBG_G(exec) = phpdbg_resolve_path(phpdbg_exec TSRMLS_CC); + if (exec) { /* set execution context */ + PHPDBG_G(exec) = phpdbg_resolve_path(exec TSRMLS_CC); PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); - free(phpdbg_exec); - phpdbg_exec = NULL; + free(exec); + exec = NULL; } if (oplog_file) { /* open oplog */ @@ -1537,7 +1567,12 @@ phpdbg_interact: } } zend_end_try(); } 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; @@ -1590,7 +1625,24 @@ phpdbg_out: /* this is just helpful */ PG(report_memleaks) = 0; - php_request_shutdown((void*)0); + if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + php_free_shutdown_functions(TSRMLS_C); + zend_objects_store_mark_destructed(&EG(objects_store) TSRMLS_CC); + } + + /* sapi_module.deactivate is where to backup things, last chance before mm_shutdown... */ + + zend_try { + php_request_shutdown(NULL); + } zend_end_try(); + + if ((PHPDBG_G(flags) & (PHPDBG_IS_QUITTING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_RUNNING) { + phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + } + + if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + settings = PHPDBG_G(backup); + } php_output_deactivate(TSRMLS_C); diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index 688ba7cdfc..57ea7ee570 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -116,6 +116,7 @@ #include "phpdbg_utils.h" #include "phpdbg_btree.h" #include "phpdbg_watch.h" +#include "phpdbg_bp.h" #ifdef PHP_WIN32 # include "phpdbg_sigio_win32.h" #endif @@ -131,71 +132,62 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); BEGIN: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE */ -/* {{{ tables */ -#define PHPDBG_BREAK_FILE 0 -#define PHPDBG_BREAK_SYM 1 -#define PHPDBG_BREAK_OPLINE 2 -#define PHPDBG_BREAK_METHOD 3 -#define PHPDBG_BREAK_COND 4 -#define PHPDBG_BREAK_OPCODE 5 -#define PHPDBG_BREAK_FUNCTION_OPLINE 6 -#define PHPDBG_BREAK_METHOD_OPLINE 7 -#define PHPDBG_BREAK_FILE_OPLINE 8 -#define PHPDBG_BREAK_MAP 9 -#define PHPDBG_BREAK_TABLES 10 /* }}} */ - /* {{{ flags */ -#define PHPDBG_HAS_FILE_BP (1<<1) -#define PHPDBG_HAS_SYM_BP (1<<2) -#define PHPDBG_HAS_OPLINE_BP (1<<3) -#define PHPDBG_HAS_METHOD_BP (1<<4) -#define PHPDBG_HAS_COND_BP (1<<5) -#define PHPDBG_HAS_OPCODE_BP (1<<6) -#define PHPDBG_HAS_FUNCTION_OPLINE_BP (1<<7) -#define PHPDBG_HAS_METHOD_OPLINE_BP (1<<8) -#define PHPDBG_HAS_FILE_OPLINE_BP (1<<9) /* }}} */ +#define PHPDBG_HAS_FILE_BP (1ULL<<1) +#define PHPDBG_HAS_PENDING_FILE_BP (1ULL<<2) +#define PHPDBG_HAS_SYM_BP (1ULL<<3) +#define PHPDBG_HAS_OPLINE_BP (1ULL<<4) +#define PHPDBG_HAS_METHOD_BP (1ULL<<5) +#define PHPDBG_HAS_COND_BP (1ULL<<6) +#define PHPDBG_HAS_OPCODE_BP (1ULL<<7) +#define PHPDBG_HAS_FUNCTION_OPLINE_BP (1ULL<<8) +#define PHPDBG_HAS_METHOD_OPLINE_BP (1ULL<<9) +#define PHPDBG_HAS_FILE_OPLINE_BP (1ULL<<10) /* }}} */ /* END: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE */ -#define PHPDBG_IN_COND_BP (1<<10) -#define PHPDBG_IN_EVAL (1<<11) +#define PHPDBG_IN_COND_BP (1ULL<<11) +#define PHPDBG_IN_EVAL (1ULL<<12) -#define PHPDBG_IS_STEPPING (1<<12) -#define PHPDBG_STEP_OPCODE (1<<13) -#define PHPDBG_IS_QUIET (1<<14) -#define PHPDBG_IS_QUITTING (1<<15) -#define PHPDBG_IS_COLOURED (1<<16) -#define PHPDBG_IS_CLEANING (1<<17) +#define PHPDBG_IS_STEPPING (1ULL<<13) +#define PHPDBG_STEP_OPCODE (1ULL<<14) +#define PHPDBG_IS_QUIET (1ULL<<15) +#define PHPDBG_IS_QUITTING (1ULL<<16) +#define PHPDBG_IS_COLOURED (1ULL<<17) +#define PHPDBG_IS_CLEANING (1ULL<<18) +#define PHPDBG_IS_RUNNING (1ULL<<19) -#define PHPDBG_IN_UNTIL (1<<18) -#define PHPDBG_IN_FINISH (1<<19) -#define PHPDBG_IN_LEAVE (1<<20) +#define PHPDBG_IN_UNTIL (1ULL<<20) +#define PHPDBG_IN_FINISH (1ULL<<21) +#define PHPDBG_IN_LEAVE (1ULL<<22) -#define PHPDBG_IS_REGISTERED (1<<21) -#define PHPDBG_IS_STEPONEVAL (1<<22) -#define PHPDBG_IS_INITIALIZING (1<<23) -#define PHPDBG_IS_SIGNALED (1<<24) -#define PHPDBG_IS_INTERACTIVE (1<<25) -#define PHPDBG_IS_BP_ENABLED (1<<26) -#define PHPDBG_IS_REMOTE (1<<27) -#define PHPDBG_IS_DISCONNECTED (1<<28) -#define PHPDBG_WRITE_XML (1<<29) +#define PHPDBG_IS_REGISTERED (1ULL<<23) +#define PHPDBG_IS_STEPONEVAL (1ULL<<24) +#define PHPDBG_IS_INITIALIZING (1ULL<<25) +#define PHPDBG_IS_SIGNALED (1ULL<<26) +#define PHPDBG_IS_INTERACTIVE (1ULL<<27) +#define PHPDBG_IS_BP_ENABLED (1ULL<<28) +#define PHPDBG_IS_REMOTE (1ULL<<29) +#define PHPDBG_IS_DISCONNECTED (1ULL<<30) +#define PHPDBG_WRITE_XML (1ULL<<31) -#define PHPDBG_SHOW_REFCOUNTS (1<<30) +#define PHPDBG_SHOW_REFCOUNTS (1ULL<<32) -#define PHPDBG_IN_SIGNAL_HANDLER (1<<30) +#define PHPDBG_IN_SIGNAL_HANDLER (1ULL<<33) #define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE) #define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) #define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) #define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING) +#define PHPDBG_PRESERVE_FLAGS_MASK (PHPDBG_SHOW_REFCOUNTS | PHPDBG_IS_STEPONEVAL | PHPDBG_IS_BP_ENABLED | PHPDBG_STEP_OPCODE) + #ifndef _WIN32 -# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED) +# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED | PHPDBG_IS_BP_ENABLED) #else -# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_BP_ENABLED) +# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_BP_ENABLED) #endif /* }}} */ /* {{{ output descriptors */ @@ -256,6 +248,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) FILE *ptr; int fd; } io[PHPDBG_IO_FDS]; /* io */ + int eol; /* type of line ending to use */ size_t (*php_stdiop_write)(php_stream *, const char *, size_t TSRMLS_DC); int in_script_xml; /* in output mode */ struct { @@ -281,17 +274,18 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) JMP_BUF *sigsegv_bailout; /* bailout address for accesibility probing */ - zend_ulong flags; /* phpdbg flags */ + uint64_t flags; /* phpdbg flags */ char *socket_path; /* phpdbg.path ini setting */ char *sapi_name_ptr; /* store sapi name to free it if necessary to not leak memory */ int socket_fd; /* file descriptor to socket (wait command) (-1 if unused) */ int socket_server_fd; /* file descriptor to master socket (wait command) (-1 if unused) */ #ifdef PHP_WIN32 - HANDLE sigio_watcher_thread; /* sigio watcher thread handle */ + HANDLE sigio_watcher_thread; /* sigio watcher thread handle */ struct win32_sigio_watcher_data swd; #endif - int8_t eol; + + struct _zend_phpdbg_globals *backup; /* backup of data to store */ ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */ #endif diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 81674a0daf..9333b353ce 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -220,51 +220,119 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML { php_stream_statbuf ssb; char realpath[MAXPATHLEN]; + const char *original_path = path; + zend_bool pending; - if (php_stream_stat_path(path, &ssb) != FAILURE) { - if (ssb.sb.st_mode & (S_IFREG|S_IFLNK)) { - HashTable *broken; - phpdbg_breakfile_t new_break; - size_t path_len = 0L; + HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE]; + phpdbg_breakfile_t new_break; + size_t path_len = 0L; - if (VCWD_REALPATH(path, realpath)) { - path = realpath; + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } + path_len = strlen(path); + + if (!zend_hash_exists(&PHPDBG_G(file_sources), path, path_len)) { + if (php_stream_stat_path(path, &ssb) == FAILURE) { + if (original_path[0] == '/') { + phpdbg_error("breakpoint", "type=\"nofile\" add=\"fail\" file=\"%s\"", "Cannot stat %s, it does not exist", original_path); + return; } + + file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]; + path = original_path; path_len = strlen(path); + pending = 1; + } else if (!(ssb.sb.st_mode & (S_IFREG|S_IFLNK))) { + phpdbg_error("breakpoint", "type=\"notregular\" add=\"fail\" file=\"%s\"", "Cannot set breakpoint in %s, it is not a regular file", path); + return; + } + } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, (void**)&broken) == FAILURE) { - HashTable breaks; + if (zend_hash_find(file_breaks, path, path_len, (void **) &broken) == FAILURE) { + HashTable breaks; + zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); - zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); + zend_hash_add(file_breaks, path, path_len, &breaks, sizeof(HashTable), (void **) &broken); + } - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, &breaks, sizeof(HashTable), - (void**)&broken); - } + if (!zend_hash_index_exists(broken, line_num)) { + PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); + new_break.filename = estrndup(path, path_len); + new_break.line = line_num; - if (!zend_hash_index_exists(broken, line_num)) { - PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + zend_hash_index_update(broken, line_num, (void **) &new_break, sizeof(phpdbg_breakfile_t), NULL); - PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); - new_break.filename = estrndup(path, path_len); - new_break.line = line_num; + if (pending) { + PHPDBG_G(flags) |= PHPDBG_HAS_PENDING_FILE_BP; - zend_hash_index_update( broken, line_num, (void**)&new_break, sizeof(phpdbg_breakfile_t), NULL); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\" pending=\"pending\"", "Pending breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); + } else { + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; - phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", - new_break.id, new_break.filename, new_break.line); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); + } - PHPDBG_BREAK_MAPPING(new_break.id, broken); - } else { - phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num); + PHPDBG_BREAK_MAPPING(new_break.id, broken); + } else { + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num); + } +} /* }}} */ + +PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file TSRMLS_DC) /* {{{ */ +{ + HashPosition position[2]; + HashTable *fileht; + uint filelen = strlen(file); + + zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position[0]); + while (zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], (void**) &fileht, &position[0]) == SUCCESS) { + const char *cur; + uint curlen; + + zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], (char **) &cur, &curlen, NULL, 0, &position[0]); + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position[0]); + + if (curlen < filelen && file[filelen - curlen - 1] == '/' && !memcmp(file + filelen - curlen, cur, curlen)) { + phpdbg_breakfile_t *brake, new_brake; + HashTable *master = NULL; + dtor_func_t dtor; + + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, (void **) &master) == FAILURE) { + dtor = PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING].pDestructor; + PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING].pDestructor = NULL; + zend_hash_add(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, fileht, sizeof(HashTable), (void **) &fileht); } - } else { - phpdbg_error("breakpoint", "type=\"notregular\" add=\"fail\" file=\"%s\"", "Cannot set breakpoint in %s, it is not a regular file", path); + for (zend_hash_internal_pointer_reset_ex(fileht, &position[1]); + zend_hash_get_current_data_ex(fileht, (void**)&brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex(fileht, &position[1])) { + new_brake = *brake; + new_brake.filename = estrndup(file, filelen); + PHPDBG_BREAK_UNMAPPING(brake->id); + + if (master) { + zend_hash_index_update(master, brake->line, (void **) &new_brake, sizeof(phpdbg_breakfile_t), NULL); + PHPDBG_BREAK_MAPPING(brake->id, master); + } else { + efree((char *) brake->filename); + *brake = new_brake; + PHPDBG_BREAK_MAPPING(brake->id, fileht); + } + } + + zend_hash_del(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur, curlen); + + if (!master) { + PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING].pDestructor = dtor; + } + + if (!zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING])) { + PHPDBG_G(flags) &= ~PHPDBG_HAS_PENDING_FILE_BP; + } } - } else { - phpdbg_error("breakpoint", "type=\"nofile\" add=\"fail\" file=\"%s\"", "Cannot stat %s, it does not exist", path); } } /* }}} */ @@ -1141,6 +1209,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -1398,6 +1467,25 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); } } + } if ((PHPDBG_G(flags) & PHPDBG_HAS_PENDING_FILE_BP)) { + HashPosition position[2]; + HashTable *points; + + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Pending File Breakpoints:\n"); + for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position[0]); + zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], (void**) &points, &position[0]) == SUCCESS; + zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position[0])) { + phpdbg_breakfile_t *brake; + + for (zend_hash_internal_pointer_reset_ex(points, &position[1]); + zend_hash_get_current_data_ex(points, (void**)&brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex(points, &position[1])) { + phpdbg_writeln("file", "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\" pending=\"pending\"", "#%d\t\t%s:%lu%s", + brake->id, brake->filename, brake->line, + ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + } + } } break; diff --git a/sapi/phpdbg/phpdbg_bp.h b/sapi/phpdbg/phpdbg_bp.h index a6227cba6c..606085ddcf 100644 --- a/sapi/phpdbg/phpdbg_bp.h +++ b/sapi/phpdbg/phpdbg_bp.h @@ -23,16 +23,17 @@ /* {{{ defines */ #define PHPDBG_BREAK_FILE 0 -#define PHPDBG_BREAK_SYM 1 -#define PHPDBG_BREAK_OPLINE 2 -#define PHPDBG_BREAK_METHOD 3 -#define PHPDBG_BREAK_COND 4 -#define PHPDBG_BREAK_OPCODE 5 -#define PHPDBG_BREAK_FUNCTION_OPLINE 6 -#define PHPDBG_BREAK_METHOD_OPLINE 7 -#define PHPDBG_BREAK_FILE_OPLINE 8 -#define PHPDBG_BREAK_MAP 9 -#define PHPDBG_BREAK_TABLES 10 /* }}} */ +#define PHPDBG_BREAK_FILE_PENDING 1 +#define PHPDBG_BREAK_SYM 2 +#define PHPDBG_BREAK_OPLINE 3 +#define PHPDBG_BREAK_METHOD 4 +#define PHPDBG_BREAK_COND 5 +#define PHPDBG_BREAK_OPCODE 6 +#define PHPDBG_BREAK_FUNCTION_OPLINE 7 +#define PHPDBG_BREAK_METHOD_OPLINE 8 +#define PHPDBG_BREAK_FILE_OPLINE 9 +#define PHPDBG_BREAK_MAP 10 +#define PHPDBG_BREAK_TABLES 11 /* }}} */ /* {{{ */ typedef struct _zend_op *phpdbg_opline_ptr_t; /* }}} */ @@ -116,10 +117,11 @@ typedef struct _phpdbg_breakcond_t { zend_op_array *ops; } phpdbg_breakcond_t; -/* {{{ Opline breaks API */ +/* {{{ Resolving breaks API */ PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array TSRMLS_DC); PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array TSRMLS_DC); -PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRMLS_DC); /* }}} */ +PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRMLS_DC); +PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file TSRMLS_DC); /* }}} */ /* {{{ Breakpoint Creation API */ PHPDBG_API void phpdbg_set_breakpoint_file(const char* filename, long lineno TSRMLS_DC); diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c index 13d5a0d634..a170d52955 100644 --- a/sapi/phpdbg/phpdbg_cmd.c +++ b/sapi/phpdbg/phpdbg_cmd.c @@ -727,7 +727,7 @@ PHPDBG_API char *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */ char *cmd = NULL; char *buffer = NULL; - if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { + if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) != PHPDBG_IS_STOPPING) { if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && (buffered == NULL) && !phpdbg_active_sigsafe_mem(TSRMLS_C)) { fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr); } diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index 7aa8c4f9e0..8ab4c8922a 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -278,6 +278,8 @@ zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type TSRMLS_DC) { dataptr->line[line] = endptr - data.buf; dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + phpdbg_resolve_pending_file_break(filename TSRMLS_CC); + ret = PHPDBG_G(compile_file)(&fake, type TSRMLS_CC); fake.opened_path = NULL; diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c index a4793f144f..365708c71e 100644 --- a/sapi/phpdbg/phpdbg_out.c +++ b/sapi/phpdbg/phpdbg_out.c @@ -1117,6 +1117,8 @@ PHPDBG_API int phpdbg_vprint(int type TSRMLS_DC, int fd, const char *tag, const } if (PHPDBG_G(err_buf).active && type != P_STDOUT && type != P_STDERR) { + phpdbg_free_err_buf(TSRMLS_C); + PHPDBG_G(err_buf).type = type; PHPDBG_G(err_buf).fd = fd; PHPDBG_G(err_buf).tag = estrdup(tag); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index eca4c6ac2b..a2e4d41042 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -28,7 +28,6 @@ #include "phpdbg_print.h" #include "phpdbg_info.h" #include "phpdbg_break.h" -#include "phpdbg_bp.h" #include "phpdbg_opcode.h" #include "phpdbg_list.h" #include "phpdbg_utils.h" @@ -44,7 +43,6 @@ ZEND_EXTERN_MODULE_GLOBALS(phpdbg); ZEND_EXTERN_MODULE_GLOBALS(output); extern int phpdbg_startup_run; -extern char *phpdbg_exec; #ifdef HAVE_LIBDL #ifdef PHP_WIN32 @@ -641,10 +639,10 @@ PHPDBG_COMMAND(run) /* {{{ */ } zend_try { - PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; + PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE; + PHPDBG_G(flags) |= PHPDBG_IS_RUNNING; zend_execute(EG(active_op_array) TSRMLS_CC); - PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; - phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; } zend_catch { EG(active_op_array) = orig_op_array; EG(opline_ptr) = orig_opline; @@ -669,7 +667,11 @@ PHPDBG_COMMAND(run) /* {{{ */ EG(active_op_array) = orig_op_array; EG(opline_ptr) = orig_opline; EG(return_value_ptr_ptr) = orig_retval_ptr; + + phpdbg_clean(1 TSRMLS_CC); } + + PHPDBG_G(flags) &= ~PHPDBG_IS_RUNNING; } else { phpdbg_error("inactive", "type=\"nocontext\"", "Nothing to execute!"); } @@ -1235,8 +1237,8 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */ PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; - while (1) { - if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + while (ret == SUCCESS || ret == FAILURE) { + if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_STOPPING) { zend_bailout(); } @@ -1291,6 +1293,7 @@ int phpdbg_interactive(zend_bool allow_async_unsafe TSRMLS_DC) /* {{{ */ phpdbg_stack_free(&stack); phpdbg_destroy_input(&input TSRMLS_CC); PHPDBG_G(req_id) = 0; + input = NULL; } if (input) { @@ -1320,10 +1323,6 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ } if (full) { - if (PHPDBG_G(exec)) { - phpdbg_exec = strdup(PHPDBG_G(exec)); /* preserve exec, don't reparse that from cmd */ - } - PHPDBG_G(flags) |= PHPDBG_IS_CLEANING; zend_bailout(); -- cgit v1.2.1 From 190f4f9f18643a306fab7a71b625bf01168b0093 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 26 Oct 2014 22:21:18 +0100 Subject: Fix last commit, and do not output unnecessary information --- sapi/phpdbg/phpdbg.c | 44 ++++++++++++++++++++---------- sapi/phpdbg/phpdbg.h | 4 ++- sapi/phpdbg/phpdbg_io.c | 4 +++ sapi/phpdbg/phpdbg_prompt.c | 11 ++++++-- sapi/phpdbg/tests/commands/0104_clean.test | 1 - 5 files changed, 46 insertions(+), 18 deletions(-) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 3e31f76898..b7fb5e5afc 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -544,7 +544,7 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */ { - if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + 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); @@ -554,7 +554,7 @@ static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */ pg->oplog = PHPDBG_G(oplog); pg->prompt[0] = PHPDBG_G(prompt)[0]; pg->prompt[1] = PHPDBG_G(prompt)[1]; - memset(pg->colors, PHPDBG_G(colors), sizeof(pg->colors)); + memcpy(pg->colors, PHPDBG_G(colors), sizeof(pg->colors)); pg->eol = PHPDBG_G(eol); pg->flags = PHPDBG_G(flags) & PHPDBG_PRESERVE_FLAGS_MASK; } @@ -1035,7 +1035,7 @@ int main(int argc, char **argv) /* {{{ */ zend_ulong flags; char *php_optarg; int php_optind, opt, show_banner = 1; - long cleaning = 0; + long cleaning = -1; zend_bool remote = 0; int step = 0; zend_phpdbg_globals *settings = NULL; @@ -1491,21 +1491,20 @@ phpdbg_main: /* Make stdin, stdout and stderr accessible from PHP scripts */ phpdbg_register_file_handles(TSRMLS_C); - if (show_banner) { + if (show_banner && cleaning < 2) { /* print blurb */ - phpdbg_welcome((cleaning > 0) TSRMLS_CC); + phpdbg_welcome(cleaning == 1 TSRMLS_CC); } - /* auto compile */ - if (PHPDBG_G(exec)) { - phpdbg_compile(TSRMLS_C); - } + cleaning = -1; /* initialize from file */ PHPDBG_G(flags) |= PHPDBG_IS_INITIALIZING; zend_try { phpdbg_init(init_file, init_file_len, init_file_default TSRMLS_CC); + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; phpdbg_try_file_init(bp_tmp_file, strlen(bp_tmp_file), 0 TSRMLS_CC); + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; } zend_end_try(); PHPDBG_G(flags) &= ~PHPDBG_IS_INITIALIZING; @@ -1514,14 +1513,24 @@ phpdbg_main: goto phpdbg_out; } + /* auto compile */ + if (PHPDBG_G(exec)) { + if (settings) { + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; + } + phpdbg_compile(TSRMLS_C); + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; + } + /* step from here, not through init */ if (step) { PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } if (phpdbg_startup_run) { - /* no need to try{}, run does it ... */ - PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC); + zend_try { + PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC); + } zend_end_try(); if (phpdbg_startup_run > 1) { /* if -r is on the command line more than once just quit */ goto phpdbg_out; @@ -1537,7 +1546,9 @@ phpdbg_interact: } zend_catch { if ((PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) { FILE *bp_tmp_fp = fopen(bp_tmp_file, "w"); + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; phpdbg_export_breakpoints(bp_tmp_fp TSRMLS_CC); + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; fclose(bp_tmp_fp); cleaning = 1; } else { @@ -1589,9 +1600,13 @@ phpdbg_out: } __except(phpdbg_exception_handler_win32(xp = GetExceptionInformation())) { phpdbg_error("segfault", "", "Access violation (Segementation fault) encountered\ntrying to abort cleanly..."); } -/* phpdbg_out: */ #endif + if (cleaning <= 0) { + PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING; + cleaning = -1; + } + { int i; /* free argv */ @@ -1638,9 +1653,10 @@ phpdbg_out: if ((PHPDBG_G(flags) & (PHPDBG_IS_QUITTING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_RUNNING) { phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + cleaning++; } - if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + if ((PHPDBG_G(flags) & PHPDBG_IS_STOPPING) == PHPDBG_IS_CLEANING) { settings = PHPDBG_G(backup); } @@ -1654,7 +1670,7 @@ phpdbg_out: } - if (cleaning || remote) { + if (cleaning > 0 || remote) { goto phpdbg_main; } diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index 57ea7ee570..65bdcd0d6f 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -177,12 +177,14 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); #define PHPDBG_IN_SIGNAL_HANDLER (1ULL<<33) +#define PHPDBG_DISCARD_OUTPUT (1ULL<<34) + #define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE) #define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) #define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) #define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING) -#define PHPDBG_PRESERVE_FLAGS_MASK (PHPDBG_SHOW_REFCOUNTS | PHPDBG_IS_STEPONEVAL | PHPDBG_IS_BP_ENABLED | PHPDBG_STEP_OPCODE) +#define PHPDBG_PRESERVE_FLAGS_MASK (PHPDBG_SHOW_REFCOUNTS | PHPDBG_IS_STEPONEVAL | PHPDBG_IS_BP_ENABLED | PHPDBG_STEP_OPCODE | PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED) #ifndef _WIN32 # define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED | PHPDBG_IS_BP_ENABLED) diff --git a/sapi/phpdbg/phpdbg_io.c b/sapi/phpdbg/phpdbg_io.c index a2a5c5969f..6908a687d7 100644 --- a/sapi/phpdbg/phpdbg_io.c +++ b/sapi/phpdbg/phpdbg_io.c @@ -187,6 +187,10 @@ PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo TSRMLS_DC PHPDBG_API int phpdbg_mixed_write(int sock, const char *ptr, int len TSRMLS_DC) { + if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) { + return 0; + } + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { return phpdbg_send_bytes(sock, ptr, len); } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index a2e4d41042..fd4af2c3cd 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -263,7 +263,7 @@ void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_ goto next_line; } - { + zend_try { char *input = phpdbg_read_input(cmd TSRMLS_CC); phpdbg_param_t stack; @@ -287,7 +287,12 @@ void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_ phpdbg_stack_free(&stack); phpdbg_destroy_input(&input TSRMLS_CC); - } + } zend_catch { + PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING); + if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) { + zend_bailout(); + } + } zend_end_try(); } next_line: line++; @@ -1160,6 +1165,8 @@ 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 TSRMLS_CC); phpdbg_xml(""); diff --git a/sapi/phpdbg/tests/commands/0104_clean.test b/sapi/phpdbg/tests/commands/0104_clean.test index d50903c479..2c7660ad60 100644 --- a/sapi/phpdbg/tests/commands/0104_clean.test +++ b/sapi/phpdbg/tests/commands/0104_clean.test @@ -9,7 +9,6 @@ #Functions %d #Constants %d #Includes %d -#[Nothing to execute!] ################################################# clean quit -- cgit v1.2.1 From 50756b515c76bb9c43a01bfce03207906f596005 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sun, 26 Oct 2014 23:33:54 +0100 Subject: Do not execute anything after quit or clean command --- sapi/phpdbg/phpdbg_prompt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sapi/phpdbg') diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index fd4af2c3cd..5e2cc03d50 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1438,6 +1438,10 @@ void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */ } #endif + if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_STOPPING) { + zend_bailout(); + } + EG(in_execution) = 1; #if PHP_VERSION_ID >= 50500 -- cgit v1.2.1