diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index b788b652979de..375b17295ef19 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -67,10 +67,8 @@ void zend_dump_const(const zval *zv) fprintf(stderr, " float(%g)", Z_DVAL_P(zv)); break; case IS_STRING:; - zend_string *escaped_string = php_addcslashes(Z_STR_P(zv), "\"\\", 2); - - fprintf(stderr, " string(\"%s\")", ZSTR_VAL(escaped_string)); - + zend_string *escaped_string = php_repr_str(Z_STR_P(zv)->val, Z_STR_P(zv)->len); + fprintf(stderr, " string(%s)", ZSTR_VAL(escaped_string)); zend_string_release(escaped_string); break; case IS_ARRAY: 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/match/005.phpt b/ext/opcache/tests/match/005.phpt new file mode 100644 index 0000000000000..448bf20fd487e --- /dev/null +++ b/ext/opcache/tests/match/005.phpt @@ -0,0 +1,36 @@ +--TEST-- +Match expression mixed jump table +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +$_main: + ; (lines=1, args=0, vars=0, tmps=0) + ; (after optimizer) + ; %s.php:1-21 +0000 RETURN string("\x00\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0b\f\r\x0e\x0f\n\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\n !\"#$%&'()*+,-./\n0123456789:;<=>?\n@ABCDEFGHIJKLMNO\nPQRSTUVWXYZ[\\]^_\n`abcdefghijklmno\npqrstuvwxyz{|}~\x7f\n\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\n\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\n\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\n\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\n\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\n\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\n\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\n\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") 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) diff --git a/ext/standard/charrepr.h b/ext/standard/charrepr.h new file mode 100644 index 0000000000000..7fb31a20d43f2 --- /dev/null +++ b/ext/standard/charrepr.h @@ -0,0 +1,284 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Yihang Wang | + +----------------------------------------------------------------------+ +*/ + +#ifndef CHARREPR_H +#define CHARREPR_H + +typedef struct { + const char *repr; + const unsigned char len; +} char_repr_t; + +static const char_repr_t char_reprs[256] = { + {"\\x00", 4}, + {"\\x01", 4}, + {"\\x02", 4}, + {"\\x03", 4}, + {"\\x04", 4}, + {"\\x05", 4}, + {"\\x06", 4}, + {"\\x07", 4}, + {"\\b", 2}, + {"\\t", 2}, + {"\\n", 2}, + {"\\x0b", 4}, + {"\\f", 2}, + {"\\r", 2}, + {"\\x0e", 4}, + {"\\x0f", 4}, + {"\\x10", 4}, + {"\\x11", 4}, + {"\\x12", 4}, + {"\\x13", 4}, + {"\\x14", 4}, + {"\\x15", 4}, + {"\\x16", 4}, + {"\\x17", 4}, + {"\\x18", 4}, + {"\\x19", 4}, + {"\\x1a", 4}, + {"\\x1b", 4}, + {"\\x1c", 4}, + {"\\x1d", 4}, + {"\\x1e", 4}, + {"\\x1f", 4}, + {" ", 1}, + {"!", 1}, + {"\\\"", 2}, + {"#", 1}, + {"$", 1}, + {"%", 1}, + {"&", 1}, + {"\'", 1}, + {"(", 1}, + {")", 1}, + {"*", 1}, + {"+", 1}, + {",", 1}, + {"-", 1}, + {".", 1}, + {"/", 1}, + {"0", 1}, + {"1", 1}, + {"2", 1}, + {"3", 1}, + {"4", 1}, + {"5", 1}, + {"6", 1}, + {"7", 1}, + {"8", 1}, + {"9", 1}, + {":", 1}, + {";", 1}, + {"<", 1}, + {"=", 1}, + {">", 1}, + {"?", 1}, + {"@", 1}, + {"A", 1}, + {"B", 1}, + {"C", 1}, + {"D", 1}, + {"E", 1}, + {"F", 1}, + {"G", 1}, + {"H", 1}, + {"I", 1}, + {"J", 1}, + {"K", 1}, + {"L", 1}, + {"M", 1}, + {"N", 1}, + {"O", 1}, + {"P", 1}, + {"Q", 1}, + {"R", 1}, + {"S", 1}, + {"T", 1}, + {"U", 1}, + {"V", 1}, + {"W", 1}, + {"X", 1}, + {"Y", 1}, + {"Z", 1}, + {"[", 1}, + {"\\\\", 2}, + {"]", 1}, + {"^", 1}, + {"_", 1}, + {"`", 1}, + {"a", 1}, + {"b", 1}, + {"c", 1}, + {"d", 1}, + {"e", 1}, + {"f", 1}, + {"g", 1}, + {"h", 1}, + {"i", 1}, + {"j", 1}, + {"k", 1}, + {"l", 1}, + {"m", 1}, + {"n", 1}, + {"o", 1}, + {"p", 1}, + {"q", 1}, + {"r", 1}, + {"s", 1}, + {"t", 1}, + {"u", 1}, + {"v", 1}, + {"w", 1}, + {"x", 1}, + {"y", 1}, + {"z", 1}, + {"{", 1}, + {"|", 1}, + {"}", 1}, + {"~", 1}, + {"\\x7f", 4}, + {"\\x80", 4}, + {"\\x81", 4}, + {"\\x82", 4}, + {"\\x83", 4}, + {"\\x84", 4}, + {"\\x85", 4}, + {"\\x86", 4}, + {"\\x87", 4}, + {"\\x88", 4}, + {"\\x89", 4}, + {"\\x8a", 4}, + {"\\x8b", 4}, + {"\\x8c", 4}, + {"\\x8d", 4}, + {"\\x8e", 4}, + {"\\x8f", 4}, + {"\\x90", 4}, + {"\\x91", 4}, + {"\\x92", 4}, + {"\\x93", 4}, + {"\\x94", 4}, + {"\\x95", 4}, + {"\\x96", 4}, + {"\\x97", 4}, + {"\\x98", 4}, + {"\\x99", 4}, + {"\\x9a", 4}, + {"\\x9b", 4}, + {"\\x9c", 4}, + {"\\x9d", 4}, + {"\\x9e", 4}, + {"\\x9f", 4}, + {"\\xa0", 4}, + {"\\xa1", 4}, + {"\\xa2", 4}, + {"\\xa3", 4}, + {"\\xa4", 4}, + {"\\xa5", 4}, + {"\\xa6", 4}, + {"\\xa7", 4}, + {"\\xa8", 4}, + {"\\xa9", 4}, + {"\\xaa", 4}, + {"\\xab", 4}, + {"\\xac", 4}, + {"\\xad", 4}, + {"\\xae", 4}, + {"\\xaf", 4}, + {"\\xb0", 4}, + {"\\xb1", 4}, + {"\\xb2", 4}, + {"\\xb3", 4}, + {"\\xb4", 4}, + {"\\xb5", 4}, + {"\\xb6", 4}, + {"\\xb7", 4}, + {"\\xb8", 4}, + {"\\xb9", 4}, + {"\\xba", 4}, + {"\\xbb", 4}, + {"\\xbc", 4}, + {"\\xbd", 4}, + {"\\xbe", 4}, + {"\\xbf", 4}, + {"\\xc0", 4}, + {"\\xc1", 4}, + {"\\xc2", 4}, + {"\\xc3", 4}, + {"\\xc4", 4}, + {"\\xc5", 4}, + {"\\xc6", 4}, + {"\\xc7", 4}, + {"\\xc8", 4}, + {"\\xc9", 4}, + {"\\xca", 4}, + {"\\xcb", 4}, + {"\\xcc", 4}, + {"\\xcd", 4}, + {"\\xce", 4}, + {"\\xcf", 4}, + {"\\xd0", 4}, + {"\\xd1", 4}, + {"\\xd2", 4}, + {"\\xd3", 4}, + {"\\xd4", 4}, + {"\\xd5", 4}, + {"\\xd6", 4}, + {"\\xd7", 4}, + {"\\xd8", 4}, + {"\\xd9", 4}, + {"\\xda", 4}, + {"\\xdb", 4}, + {"\\xdc", 4}, + {"\\xdd", 4}, + {"\\xde", 4}, + {"\\xdf", 4}, + {"\\xe0", 4}, + {"\\xe1", 4}, + {"\\xe2", 4}, + {"\\xe3", 4}, + {"\\xe4", 4}, + {"\\xe5", 4}, + {"\\xe6", 4}, + {"\\xe7", 4}, + {"\\xe8", 4}, + {"\\xe9", 4}, + {"\\xea", 4}, + {"\\xeb", 4}, + {"\\xec", 4}, + {"\\xed", 4}, + {"\\xee", 4}, + {"\\xef", 4}, + {"\\xf0", 4}, + {"\\xf1", 4}, + {"\\xf2", 4}, + {"\\xf3", 4}, + {"\\xf4", 4}, + {"\\xf5", 4}, + {"\\xf6", 4}, + {"\\xf7", 4}, + {"\\xf8", 4}, + {"\\xf9", 4}, + {"\\xfa", 4}, + {"\\xfb", 4}, + {"\\xfc", 4}, + {"\\xfd", 4}, + {"\\xfe", 4}, + {"\\xff", 4}, +}; + +#endif diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 51c537de6e628..1fac48d0fff81 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -38,6 +38,7 @@ PHPAPI char *php_strtr(char *str, size_t len, const char *str_from, const char * PHPAPI zend_string *php_addslashes(zend_string *str); PHPAPI void php_stripslashes(zend_string *str); PHPAPI zend_string *php_addcslashes_str(const char *str, size_t len, const char *what, size_t what_len); +PHPAPI zend_string *php_repr_str(const char *str, size_t len); PHPAPI zend_string *php_addcslashes(zend_string *str, const char *what, size_t what_len); PHPAPI void php_stripcslashes(zend_string *str); PHPAPI zend_string *php_basename(const char *s, size_t len, const char *suffix, size_t sufflen); diff --git a/ext/standard/string.c b/ext/standard/string.c index 9f7e0ff60d3a8..1984771c708b0 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -32,6 +32,9 @@ #include "scanf.h" #include "zend_API.h" #include "zend_execute.h" +#include "zend_string.h" +#include "charrepr.h" +#include "php_globals.h" #include "basic_functions.h" #include "zend_smart_str.h" #include @@ -3832,6 +3835,38 @@ PHPAPI zend_string *php_addcslashes_str(const char *str, size_t len, const char } /* }}} */ +/* {{{ php_repr_str */ +PHPAPI zend_string *php_repr_str(const char *str, size_t len) { + size_t newlen; + // allocate enough memory for the worst case scenario + // in which every character is a control character + // and we need to represent it as \x00 (4 bytes) + // so we need 4 bytes for each character + // plus 2 byte for the leading quote and the trailing quote + // plus 1 byte for the null terminator + int alloc_len = len * 4 + 2 + 1; + zend_string *new_str = zend_string_alloc(alloc_len, 0); + char *target = ZSTR_VAL(new_str); + // add the leading quote + *target++ = '"'; + for (size_t i = 0; i < len; i++) { + const char *repr = char_reprs[(unsigned char)str[i]].repr; + size_t repr_len = char_reprs[(unsigned char)str[i]].len; + memcpy(target, repr, repr_len); + target += repr_len; + } + // add the trailing quote + *target++ = '"'; + // add the null terminator + *target = '\0'; + newlen = target - ZSTR_VAL(new_str); + if (newlen < alloc_len) { + new_str = zend_string_truncate(new_str, newlen, 0); + } + return new_str; +} + + /* {{{ php_addcslashes */ PHPAPI zend_string *php_addcslashes(zend_string *str, const char *what, size_t wlength) {