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_bp.c | 148 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 30 deletions(-) (limited to 'sapi/phpdbg/phpdbg_bp.c') 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; -- cgit v1.2.1 From 79c66e7cd20e9e89c932781c93e2c880a6318ecd Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 28 Oct 2014 12:38:07 +0100 Subject: Fix potential segfaults and unresolved breaks --- sapi/phpdbg/phpdbg_bp.c | 56 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 19 deletions(-) (limited to 'sapi/phpdbg/phpdbg_bp.c') diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index cf28a33885..93902f0052 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -232,6 +232,8 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML } path_len = strlen(path); + phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_exists(&PHPDBG_G(file_sources), path, path_len)); + if (!zend_hash_exists(&PHPDBG_G(file_sources), path, path_len)) { if (php_stream_stat_path(path, &ssb) == FAILURE) { if (original_path[0] == '/') { @@ -246,6 +248,8 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML } 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; + } else { + phpdbg_debug("File exists, but not compiled\n"); } } @@ -273,9 +277,13 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(file_sources), &position); zend_hash_get_current_key_ex(&PHPDBG_G(file_sources), &file, &filelen, NULL, 0, &position) == HASH_KEY_IS_STRING; zend_hash_move_forward_ex(&PHPDBG_G(file_sources), &position)) { - if (!(pending = ((broken = phpdbg_resolve_pending_file_break_ex(file, filelen, path, path_len, broken TSRMLS_CC)) == NULL))) { + HashTable *fileht; + + phpdbg_debug("Compare against loaded %s\n", file); + + if (!(pending = ((fileht = phpdbg_resolve_pending_file_break_ex(file, filelen, path, path_len, broken TSRMLS_CC)) == NULL))) { phpdbg_breakfile_t *brake; - zend_hash_index_find(broken, line_num, (void **) &brake); + zend_hash_index_find(fileht, line_num, (void **) &brake); new_break = *brake; break; } @@ -298,18 +306,19 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, const char *cur, uint curlen, HashTable *fileht TSRMLS_DC) /* {{{ */ { - if (curlen < filelen && file[filelen - curlen - 1] == '/' && !memcmp(file + filelen - curlen, cur, curlen)) { + phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, cur, curlen, filelen > curlen ? file[filelen - curlen - 1] : '?', filelen > curlen ? memcmp(file + filelen - curlen, cur, curlen) : 0); + + if (((curlen < filelen && file[filelen - curlen - 1] == '/') || filelen == curlen) && !memcmp(file + filelen - curlen, cur, curlen)) { phpdbg_breakfile_t *brake, new_brake; HashTable *master = NULL; HashPosition position; - 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); + HashTable new_ht; + zend_hash_init(&new_ht, 8, NULL, phpdbg_file_breaks_dtor, 0); + zend_hash_add(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, &new_ht, sizeof(HashTable), (void **) &master); } for (zend_hash_internal_pointer_reset_ex(fileht, &position); @@ -322,24 +331,18 @@ PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uin 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; } - return fileht; + phpdbg_debug("compiled file: %s, cur bp file: %s\n", file, cur); + + return master; } return NULL; @@ -351,6 +354,8 @@ PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file TSRMLS_DC) /* HashTable *fileht; uint filelen = strlen(file); + phpdbg_debug("was compiled: %s\n", file); + zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position); while (zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], (void**) &fileht, &position) == SUCCESS) { const char *cur; @@ -359,6 +364,8 @@ PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file TSRMLS_DC) /* zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], (char **) &cur, &curlen, NULL, 0, &position); zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], &position); + phpdbg_debug("check bp: %s\n", cur); + phpdbg_resolve_pending_file_break_ex(file, filelen, cur, curlen, fileht TSRMLS_CC); } } @@ -877,10 +884,21 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_ { HashTable *breaks; phpdbg_breakbase_t *brake; - size_t name_len = strlen(op_array->filename); + size_t path_len; + char realpath[MAXPATHLEN]; + const char *path = op_array->filename; + + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } + + path_len = strlen(path); + +#if 0 + phpdbg_debug("Op at: %.*s %d\n", path_len, path, (*EG(opline_ptr))->lineno); +#endif - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename, - name_len, (void**)&breaks) == FAILURE) { + if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len, (void**)&breaks) == FAILURE) { return NULL; } -- cgit v1.2.1 From 297baa0c18d8d04de7a683a51b9f069c84a855f3 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 28 Oct 2014 17:20:21 +0100 Subject: Remove the ugly hack via a temp file to store breakpoints --- sapi/phpdbg/phpdbg_bp.c | 67 +++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 24 deletions(-) (limited to 'sapi/phpdbg/phpdbg_bp.c') diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 93902f0052..33824d4fec 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -110,11 +110,20 @@ PHPDBG_API void phpdbg_reset_breakpoints(TSRMLS_D) /* {{{ */ } /* }}} */ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ +{ + char *string; + phpdbg_export_breakpoints_to_string(&string TSRMLS_CC); + fputs(string, handle); +} + +PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str TSRMLS_DC) /* {{{ */ { HashPosition position[2]; HashTable **table = NULL; zend_ulong id = 0L; + *str = ""; + if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { phpdbg_notice("exportbreakpoint", "count=\"%d\"", "Exporting %d breakpoints", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])); /* this only looks like magic, it isn't */ @@ -126,55 +135,57 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], NULL, NULL, &id, 0, &position[0]); for (zend_hash_internal_pointer_reset_ex((*table), &position[1]); - zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex((*table), &position[1])) { + zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS; + zend_hash_move_forward_ex((*table), &position[1])) { if (brake->id == id) { + char *new_str = NULL; + switch (brake->type) { case PHPDBG_BREAK_FILE: { - fprintf(handle, - "break %s:%lu\n", + phpdbg_asprintf(&new_str, + "%sbreak %s:%lu\n", *str, ((phpdbg_breakfile_t*)brake)->filename, ((phpdbg_breakfile_t*)brake)->line); } break; case PHPDBG_BREAK_SYM: { - fprintf(handle, - "break %s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s\n", *str, ((phpdbg_breaksymbol_t*)brake)->symbol); } break; case PHPDBG_BREAK_METHOD: { - fprintf(handle, - "break %s::%s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s::%s\n", *str, ((phpdbg_breakmethod_t*)brake)->class_name, ((phpdbg_breakmethod_t*)brake)->func_name); } break; case PHPDBG_BREAK_METHOD_OPLINE: { - fprintf(handle, - "break %s::%s#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s::%s#%ld\n", *str, ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FUNCTION_OPLINE: { - fprintf(handle, - "break %s#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s#%ld\n", *str, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FILE_OPLINE: { - fprintf(handle, - "break %s:#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s:#%ld\n", *str, ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_OPCODE: { - fprintf(handle, - "break %s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s\n", *str, ((phpdbg_breakop_t*)brake)->name); } break; @@ -184,20 +195,20 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ if (conditional->paramed) { switch (conditional->param.type) { case STR_PARAM: - fprintf(handle, - "break at %s if %s\n", conditional->param.str, conditional->code); + phpdbg_asprintf(&new_str, + "%sbreak at %s if %s\n", *str, conditional->param.str, conditional->code); break; case METHOD_PARAM: - fprintf(handle, - "break at %s::%s if %s\n", + phpdbg_asprintf(&new_str, + "%sbreak at %s::%s if %s\n", *str, conditional->param.method.class, conditional->param.method.name, conditional->code); break; case FILE_PARAM: - fprintf(handle, - "break at %s:%lu if %s\n", + phpdbg_asprintf(&new_str, + "%sbreak at %s:%lu if %s\n", *str, conditional->param.file.name, conditional->param.file.line, conditional->code); break; @@ -205,15 +216,23 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ default: { /* do nothing */ } break; } } else { - fprintf( - handle, "break if %s\n", conditional->code); + phpdbg_asprintf(&new_str, "%sbreak if %s\n", str, conditional->code); } } break; } + + if ((*str)[0]) { + efree(*str); + } + *str = new_str; } } } } + + if (!(*str)[0]) { + *str = NULL; + } } /* }}} */ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */ -- cgit v1.2.1