switch (top->type) {
case EVAL_PARAM:
- if (allow_async_unsafe) {
- return PHPDBG_COMMAND_HANDLER(ev)(top TSRMLS_CC);
- }
- spprintf(why, 0, "ev command is disallowed during hard interrupt");
- return FAILURE;
+ return PHPDBG_COMMAND_HANDLER(ev)(top TSRMLS_CC);
case RUN_PARAM:
if (allow_async_unsafe) {
PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 0, PHPDBG_ASYNC_SAFE),
PHPDBG_COMMAND_D(continue,"continue execution", 'c', NULL, 0, PHPDBG_ASYNC_SAFE),
PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, "|s", 0),
- PHPDBG_COMMAND_D(ev, "evaluate some code", 0 , NULL, "i", 0), /* restricted ASYNC_SAFE */
+ PHPDBG_COMMAND_D(ev, "evaluate some code", 0 , NULL, "i", PHPDBG_ASYNC_SAFE), /* restricted ASYNC_SAFE */
PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0, 0),
PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0, 0),
PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0, 0),
return SUCCESS;
} /* }}} */
+int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv TSRMLS_DC) {
+ phpdbg_notice("Printing variable %.*s", (int) len, name);
+ zend_print_zval_r(*zv, 0 TSRMLS_CC);
+ phpdbg_writeln(EMPTY);
+ efree(name);
+ efree(keyname);
+
+ return SUCCESS;
+}
+
PHPDBG_COMMAND(ev) /* {{{ */
{
zend_bool stepping = ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING)==PHPDBG_IS_STEPPING);
zval retval;
+ if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
+ phpdbg_try_access {
+ phpdbg_parse_variable(param->str, param->len, &EG(symbol_table), 0, phpdbg_output_ev_variable, 0 TSRMLS_CC);
+ } phpdbg_catch_access {
+ phpdbg_error("Could not fetch data, invalid data source");
+ } phpdbg_end_try_access();
+ return SUCCESS;
+ }
+
if (!(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) {
- PHPDBG_G(flags) &= ~ PHPDBG_IS_STEPPING;
+ PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING;
}
/* disable stepping while eval() in progress */
zend_try {
if (zend_eval_stringl(param->str, param->len,
&retval, "eval()'d code" TSRMLS_CC) == SUCCESS) {
- zend_print_zval_r(
- &retval, 0 TSRMLS_CC);
+ zend_print_zval_r(&retval, 0 TSRMLS_CC);
phpdbg_writeln(EMPTY);
zval_dtor(&retval);
}
}
if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) {
+ PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED;
+
phpdbg_writeln(EMPTY);
phpdbg_notice("Program received signal SIGINT");
DO_INTERACTIVE(1);
}
- PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED;
next:
PHPDBG_G(last_line) = execute_data->opline->lineno;
return zend_lookup_class(name, name_length, ce TSRMLS_CC);
}
}
+
+char *phpdbg_get_property_key(char *key) {
+ if (*key != 0) {
+ return key;
+ }
+ return strchr(key + 1, 0) + 1;
+}
+
+static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, phpdbg_parse_var_func callback TSRMLS_DC) {
+ return callback(name, len, keyname, keylen, parent, zv TSRMLS_CC);
+}
+
+PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent TSRMLS_DC) {
+ return phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_parse_variable_arg_wrapper, silent, callback TSRMLS_CC);
+}
+
+PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg TSRMLS_DC) {
+ int ret = FAILURE;
+ zend_bool new_index = 1;
+ char *last_index;
+ size_t index_len = 0;
+ zval **zv;
+
+ if (len < 2 || *input != '$') {
+ goto error;
+ }
+
+ while (i++ < len) {
+ if (i == len) {
+ new_index = 1;
+ } else {
+ switch (input[i]) {
+ case '[':
+ new_index = 1;
+ break;
+ case ']':
+ break;
+ case '>':
+ if (last_index[index_len - 1] == '-') {
+ new_index = 1;
+ index_len--;
+ }
+ break;
+
+ default:
+ if (new_index) {
+ last_index = input + i;
+ new_index = 0;
+ }
+ if (input[i - 1] == ']') {
+ goto error;
+ }
+ index_len++;
+ }
+ }
+
+ if (new_index && index_len == 0) {
+ HashPosition position;
+ for (zend_hash_internal_pointer_reset_ex(parent, &position);
+ zend_hash_get_current_data_ex(parent, (void **)&zv, &position) == SUCCESS;
+ zend_hash_move_forward_ex(parent, &position)) {
+ if (i == len || (i == len - 1 && input[len - 1] == ']')) {
+ zval *key = emalloc(sizeof(zval));
+ size_t namelen;
+ char *name;
+ char *keyname = estrndup(last_index, index_len);
+ zend_hash_get_current_key_zval_ex(parent, key, &position);
+ convert_to_string(key);
+ name = emalloc(i + Z_STRLEN_P(key) + 2);
+ namelen = sprintf(name, "%.*s%s%s", (int)i, input, phpdbg_get_property_key(Z_STRVAL_P(key)), input[len - 1] == ']'?"]":"");
+ efree(key);
+
+ ret = callback(name, namelen, keyname, index_len, parent, zv, arg TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
+ } else if (Z_TYPE_PP(zv) == IS_OBJECT) {
+ phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_PP(zv), i, callback, silent, arg TSRMLS_CC);
+ } else if (Z_TYPE_PP(zv) == IS_ARRAY) {
+ phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_PP(zv), i, callback, silent, arg TSRMLS_CC);
+ } else {
+ /* Ignore silently */
+ }
+ }
+ return ret;
+ } else if (new_index) {
+ char last_chr = last_index[index_len];
+ last_index[index_len] = 0;
+ if (zend_symtable_find(parent, last_index, index_len + 1, (void **)&zv) == FAILURE) {
+ if (!silent) {
+ phpdbg_error("%.*s is undefined", (int)i, input);
+ }
+ return FAILURE;
+ }
+ last_index[index_len] = last_chr;
+ if (i == len) {
+ char *name = estrndup(input, len);
+ char *keyname = estrndup(last_index, index_len);
+
+ ret = callback(name, len, keyname, index_len, parent, zv, arg TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
+ } else if (Z_TYPE_PP(zv) == IS_OBJECT) {
+ parent = Z_OBJPROP_PP(zv);
+ } else if (Z_TYPE_PP(zv) == IS_ARRAY) {
+ parent = Z_ARRVAL_PP(zv);
+ } else {
+ phpdbg_error("%.*s is nor an array nor an object", (int)i, input);
+ return FAILURE;
+ }
+ index_len = 0;
+ }
+ }
+
+ return ret;
+ error:
+ phpdbg_error("Malformed input");
+ return FAILURE;
+}
int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
+char *phpdbg_get_property_key(char *key);
+
+typedef int (*phpdbg_parse_var_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv TSRMLS_DC);
+typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, void *arg TSRMLS_DC);
+
+PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent TSRMLS_DC);
+PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg TSRMLS_DC);
+
#endif /* PHPDBG_UTILS_H */
return SUCCESS;
}
-static char *phpdbg_get_property_key(char *key) {
- if (*key != 0) {
- return key;
- }
- return strchr(key + 1, 0) + 1;
-}
-
static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) {
HashTable *ht;
ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len);
}
- free(tmp_watch->str);
+ efree(tmp_watch->str);
+ efree(tmp_watch->name_in_parent);
efree(tmp_watch);
return ret;
}
-static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, size_t i, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC), zend_bool silent TSRMLS_DC) {
- int ret = FAILURE;
- zend_bool new_index = 1;
- char *last_index;
- int index_len = 0;
- zval **zv;
-
- if (len < 2 || *input != '$') {
- goto error;
- }
-
- while (i++ < len) {
- if (i == len) {
- new_index = 1;
- } else {
- switch (input[i]) {
- case '[':
- new_index = 1;
- break;
- case ']':
- break;
- case '>':
- if (last_index[index_len - 1] == '-') {
- new_index = 1;
- index_len--;
- }
- break;
-
- default:
- if (new_index) {
- last_index = input + i;
- new_index = 0;
- }
- if (input[i - 1] == ']') {
- goto error;
- }
- index_len++;
- }
- }
-
- if (new_index && index_len == 0) {
- HashPosition position;
- for (zend_hash_internal_pointer_reset_ex(parent, &position);
- zend_hash_get_current_data_ex(parent, (void **)&zv, &position) == SUCCESS;
- zend_hash_move_forward_ex(parent, &position)) {
- if (i == len || (i == len - 1 && input[len - 1] == ']')) {
- zval *key = emalloc(sizeof(zval));
- phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t));
- watch->flags = 0;
- zend_hash_get_current_key_zval_ex(parent, key, &position);
- convert_to_string(key);
- watch->str = malloc(i + Z_STRLEN_P(key) + 2);
- watch->str_len = sprintf(watch->str, "%.*s%s%s", (int)i, input, phpdbg_get_property_key(Z_STRVAL_P(key)), input[len - 1] == ']'?"]":"");
- efree(key);
- watch->name_in_parent = zend_strndup(last_index, index_len);
- watch->name_in_parent_len = index_len;
- watch->parent_container = parent;
- phpdbg_create_zval_watchpoint(*zv, watch);
-
- ret = callback(watch TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
- } else if (Z_TYPE_PP(zv) == IS_OBJECT) {
- phpdbg_watchpoint_parse_input(input, len, Z_OBJPROP_PP(zv), i, callback, silent TSRMLS_CC);
- } else if (Z_TYPE_PP(zv) == IS_ARRAY) {
- phpdbg_watchpoint_parse_input(input, len, Z_ARRVAL_PP(zv), i, callback, silent TSRMLS_CC);
- } else {
- /* Ignore silently */
- }
- }
- return ret;
- } else if (new_index) {
- char last_chr = last_index[index_len];
- last_index[index_len] = 0;
- if (zend_symtable_find(parent, last_index, index_len + 1, (void **)&zv) == FAILURE) {
- if (!silent) {
- phpdbg_error("%.*s is undefined", (int)i, input);
- }
- return FAILURE;
- }
- last_index[index_len] = last_chr;
- if (i == len) {
- phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t));
- watch->flags = 0;
- watch->str = zend_strndup(input, len);
- watch->str_len = len;
- watch->name_in_parent = zend_strndup(last_index, index_len);
- watch->name_in_parent_len = index_len;
- watch->parent_container = parent;
- phpdbg_create_zval_watchpoint(*zv, watch);
-
- ret = callback(watch TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
- } else if (Z_TYPE_PP(zv) == IS_OBJECT) {
- parent = Z_OBJPROP_PP(zv);
- } else if (Z_TYPE_PP(zv) == IS_ARRAY) {
- parent = Z_ARRVAL_PP(zv);
- } else {
- phpdbg_error("%.*s is nor an array nor an object", (int)i, input);
- return FAILURE;
- }
- index_len = 0;
- }
+static int phpdbg_watchpoint_parse_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval **zv, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) {
+ int ret;
+ phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t));
+ watch->flags = 0;
+ watch->str = name;
+ watch->str_len = len;
+ watch->name_in_parent = keyname;
+ watch->name_in_parent_len = keylen;
+ watch->parent_container = parent;
+ phpdbg_create_zval_watchpoint(*zv, watch);
+
+ ret = callback(watch TSRMLS_CC);
+
+ if (ret != SUCCESS) {
+ efree(watch);
+ efree(name);
+ efree(keyname);
}
return ret;
- error:
- phpdbg_error("Malformed input");
- return FAILURE;
+}
+
+PHPDBG_API int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, size_t i, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC), zend_bool silent TSRMLS_DC) {
+ phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_watchpoint_parse_wrapper, 0, callback TSRMLS_CC);
}
static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) {
phpdbg_deactivate_watchpoint(watch TSRMLS_CC);
phpdbg_remove_watchpoint(watch TSRMLS_CC);
- free(watch->str);
- free(watch->name_in_parent);
+ efree(watch->str);
+ efree(watch->name_in_parent);
efree(watch);
}