From ba75d4c50b973f6b85e8d6abab79d8c3aee2737a Mon Sep 17 00:00:00 2001
From: Bob Weinand <bobwei9@hotmail.com>
Date: Sun, 13 Nov 2016 12:55:35 +0100
Subject: [PATCH] Properly escape all filenames when exporting breakpoints

---
 sapi/phpdbg/phpdbg_bp.c               | 19 +++++++++++++------
 sapi/phpdbg/phpdbg_lexer.c            |  2 +-
 sapi/phpdbg/phpdbg_lexer.l            |  2 +-
 sapi/phpdbg/phpdbg_utils.c            |  2 +-
 sapi/phpdbg/tests/exceptions_003.phpt |  4 ++--
 sapi/phpdbg/tests/info_001.phpt       |  2 +-
 6 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c
index bb9d37b29e..5b70fe8bbb 100644
--- a/sapi/phpdbg/phpdbg_bp.c
+++ b/sapi/phpdbg/phpdbg_bp.c
@@ -25,6 +25,7 @@
 #include "phpdbg_utils.h"
 #include "phpdbg_opcode.h"
 #include "zend_globals.h"
+#include "ext/standard/php_string.h"
 
 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
 
@@ -135,10 +136,12 @@ PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str) /* {{{ */
 
 					switch (brake->type) {
 						case PHPDBG_BREAK_FILE: {
+							zend_string *filename = php_addcslashes(zend_string_init(((phpdbg_breakfile_t*)brake)->filename, strlen(((phpdbg_breakfile_t*)brake)->filename), 0), 1, "\\\"\n", 3);
 							phpdbg_asprintf(&new_str,
 								"%sbreak \"%s\":%lu\n", *str,
-								((phpdbg_breakfile_t*)brake)->filename,
+								ZSTR_VAL(filename),
 								((phpdbg_breakfile_t*)brake)->line);
+							zend_string_release(filename);
 						} break;
 
 						case PHPDBG_BREAK_SYM: {
@@ -170,10 +173,12 @@ PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str) /* {{{ */
 						} break;
 
 						case PHPDBG_BREAK_FILE_OPLINE: {
+							zend_string *filename = php_addcslashes(zend_string_init(((phpdbg_breakopline_t*)brake)->class_name, strlen(((phpdbg_breakopline_t*)brake)->class_name), 0), 1, "\\\"\n", 3);
 							phpdbg_asprintf(&new_str,
-								"%sbreak %s:#%llu\n", *str,
-								((phpdbg_breakopline_t*)brake)->class_name,
+								"%sbreak \"%s\":#%llu\n", *str,
+								filename,
 								((phpdbg_breakopline_t*)brake)->opline_num);
+							zend_string_release(filename);
 						} break;
 
 						case PHPDBG_BREAK_OPCODE: {
@@ -199,12 +204,14 @@ PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str) /* {{{ */
 											conditional->code);
 									break;
 
-									case FILE_PARAM:
+									case FILE_PARAM: {
+										zend_string *filename = php_addcslashes(zend_string_init(conditional->param.file.name, strlen(conditional->param.file.name), 0), 1, "\\\"\n", 3);
 										phpdbg_asprintf(&new_str,
-											"%sbreak at %s:%lu if %s\n", *str,
+											"%sbreak at \"%s\":%lu if %s\n", *str,
 											conditional->param.file.name, conditional->param.file.line,
 											conditional->code);
-									break;
+										zend_string_release(filename);
+									} break;
 
 									default: { /* do nothing */ } break;
 								}
diff --git a/sapi/phpdbg/phpdbg_lexer.c b/sapi/phpdbg/phpdbg_lexer.c
index d93c66f94d..74cad5b8f2 100644
--- a/sapi/phpdbg/phpdbg_lexer.c
+++ b/sapi/phpdbg/phpdbg_lexer.c
@@ -534,7 +534,7 @@ yy39:
 #line 161 "sapi/phpdbg/phpdbg_lexer.l"
 		{
 	phpdbg_init_param(yylval, STR_PARAM);
-	yylval->str = estrndup(yytext + (*yytext == '\'' || *yytext == '\"'), yyleng - unescape_string(yytext));
+	yylval->str = estrndup(yytext, yyleng - unescape_string(yytext));
 	yylval->len = yyleng;
 	return T_ID;
 }
diff --git a/sapi/phpdbg/phpdbg_lexer.l b/sapi/phpdbg/phpdbg_lexer.l
index 820eac7f84..422cda4f2c 100644
--- a/sapi/phpdbg/phpdbg_lexer.l
+++ b/sapi/phpdbg/phpdbg_lexer.l
@@ -160,7 +160,7 @@ INPUT       ("\\"[#"']|["]("\\\\"|"\\"["]|[^\n\000"])+["]|[']("\\"[']|"\\\\"|[^\
 
 <NORMAL>{GENERIC_ID} {
 	phpdbg_init_param(yylval, STR_PARAM);
-	yylval->str = estrndup(yytext + (*yytext == '\'' || *yytext == '\"'), yyleng - unescape_string(yytext));
+	yylval->str = estrndup(yytext, yyleng - unescape_string(yytext));
 	yylval->len = yyleng;
 	return T_ID;
 }
diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
index 7158f3ba6c..36537cb67c 100644
--- a/sapi/phpdbg/phpdbg_utils.c
+++ b/sapi/phpdbg/phpdbg_utils.c
@@ -807,7 +807,7 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */
 			break;
 		case IS_STRING: {
 			int i;
-			zend_string *str = php_addcslashes(Z_STR_P(zv), 0, "\\\"", 2);
+			zend_string *str = php_addcslashes(Z_STR_P(zv), 0, "\\\"\n\t\0", 5);
 			for (i = 0; i < ZSTR_LEN(str); i++) {
 				if (ZSTR_VAL(str)[i] < 32) {
 					ZSTR_VAL(str)[i] = ' ';
diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt
index 252fe32f1a..988e0c2d06 100644
--- a/sapi/phpdbg/tests/exceptions_003.phpt
+++ b/sapi/phpdbg/tests/exceptions_003.phpt
@@ -20,7 +20,7 @@ prompt> [L0 %s HANDLE_EXCEPTION
 >00005: 		x();
  00006: 	} finally {
  00007: 		print "ok\n";
-prompt> [L7 %s ECHO                    "ok "                                                          %s]
+prompt> [L7 %s ECHO                    "ok\n"                                                         %s]
 >00007: 		print "ok\n";
  00008: 	}
  00009: } catch (Error $e) {
@@ -30,7 +30,7 @@ prompt> ok
 >00005: 		x();
  00006: 	} finally {
  00007: 		print "ok\n";
-prompt> [L10 %s ECHO                    "caught "                                                      %s]
+prompt> [L10 %s ECHO                    "caught\n"                                                     %s]
 >00010: 	print "caught\n";
  00011: }
  00012: 
diff --git a/sapi/phpdbg/tests/info_001.phpt b/sapi/phpdbg/tests/info_001.phpt
index b988235757..2f38fd36af 100644
--- a/sapi/phpdbg/tests/info_001.phpt
+++ b/sapi/phpdbg/tests/info_001.phpt
@@ -32,7 +32,7 @@ prompt> string(4) "test"
  00017: 
 prompt> [Variables in foo() (1)]
 Address            Refs    Type      Variable
-%s 1       string    $baz
+%s %d       string    $baz
 string (4) "test"
 prompt> [Superglobal variables (8)]
 Address            Refs    Type      Variable
-- 
2.40.0