From 989f696037988cc6ea3f91d0e13b98def9f9f7ed Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 26 Dec 2024 20:09:42 +0100 Subject: [PATCH] Implement GH-15680: Enhance zend_dump_op_array to Properly Represent Non-Printable Characters in String Literals Replaces GH-15730 as that PR became stale. But instead of introducing a new helper, reuse smart_str_append_escaped(), this also removes the dependency on ext/standard. --- Zend/Optimizer/zend_dump.c | 24 +++++++++++++++++++----- ext/opcache/tests/match/002.phpt | 6 ++---- ext/opcache/tests/opt/dce_009.phpt | 6 ++---- ext/opcache/tests/opt/sccp_032.phpt | 3 +-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index b788b652979de..4e46b38a8eb5e 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -23,7 +23,7 @@ #include "zend_func_info.h" #include "zend_call_graph.h" #include "zend_dump.h" -#include "ext/standard/php_string.h" +#include "zend_smart_str.h" void zend_dump_ht(HashTable *ht) { @@ -66,13 +66,27 @@ void zend_dump_const(const zval *zv) case IS_DOUBLE: fprintf(stderr, " float(%g)", Z_DVAL_P(zv)); break; - case IS_STRING:; - zend_string *escaped_string = php_addcslashes(Z_STR_P(zv), "\"\\", 2); + case IS_STRING: { + smart_str escaped_string = {0}; + smart_str_append_escaped(&escaped_string, Z_STRVAL_P(zv), Z_STRLEN_P(zv)); + smart_str_0(&escaped_string); - fprintf(stderr, " string(\"%s\")", ZSTR_VAL(escaped_string)); + fprintf(stderr, " string(\""); - zend_string_release(escaped_string); + /* Also escape '"' */ + for (size_t i = 0; i < ZSTR_LEN(escaped_string.s); i++) { + if (ZSTR_VAL(escaped_string.s)[i] == '"') { + fprintf(stderr, "\\\""); + } else { + putc(ZSTR_VAL(escaped_string.s)[i], stderr); + } + } + + fprintf(stderr, "\")"); + + smart_str_free_ex(&escaped_string, false); break; + } case IS_ARRAY: fprintf(stderr, " array(...)"); break; diff --git a/ext/opcache/tests/match/002.phpt b/ext/opcache/tests/match/002.phpt index 8e7102d539120..005c2689d1b8a 100644 --- a/ext/opcache/tests/match/002.phpt +++ b/ext/opcache/tests/match/002.phpt @@ -44,16 +44,14 @@ test: ; (lines=2, args=0, vars=0, tmps=0) ; (after optimizer) ; %s -0000 ECHO string("No match -") +0000 ECHO string("No match\n") 0001 RETURN null test2: ; (lines=2, args=0, vars=0, tmps=0) ; (after optimizer) ; %s -0000 ECHO string("No match -") +0000 ECHO string("No match\n") 0001 RETURN null No match No match diff --git a/ext/opcache/tests/opt/dce_009.phpt b/ext/opcache/tests/opt/dce_009.phpt index f9c10074fb66c..996825cf96e1a 100644 --- a/ext/opcache/tests/opt/dce_009.phpt +++ b/ext/opcache/tests/opt/dce_009.phpt @@ -50,10 +50,8 @@ Loop::test: ; (lines=3, args=0, vars=0, tmps=0) ; (after optimizer) ; %sdce_009.php:4-10 -0000 ECHO string("Start -") -0001 ECHO string("Done -") +0000 ECHO string("Start\n") +0001 ECHO string("Done\n") 0002 RETURN null Loop::test2: diff --git a/ext/opcache/tests/opt/sccp_032.phpt b/ext/opcache/tests/opt/sccp_032.phpt index dac09a7552745..6ee4a837ecd37 100644 --- a/ext/opcache/tests/opt/sccp_032.phpt +++ b/ext/opcache/tests/opt/sccp_032.phpt @@ -36,8 +36,7 @@ $_main: 0004 INIT_FCALL 1 %d string("var_export") 0005 SEND_VAR CV0($x) 1 0006 DO_ICALL -0007 ECHO string(" -") +0007 ECHO string("\n") 0008 JMP 0003 0009 FE_FREE V1 0010 RETURN int(1)