Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Zend/Optimizer/zend_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

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:
Expand Down
6 changes: 2 additions & 4 deletions ext/opcache/tests/match/002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
36 changes: 36 additions & 0 deletions ext/opcache/tests/match/005.phpt
Original file line number Diff line number Diff line change
@@ -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--
<?php
return <<<EOT
\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f
\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f
\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f
\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f
\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f
\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f
\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f
\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f
\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f
\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f
\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf
\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf
\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf
\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf
\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef
\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
EOT;
?>
--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\x08\t\n\x0b\x0c\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")
6 changes: 2 additions & 4 deletions ext/opcache/tests/opt/dce_009.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 1 addition & 2 deletions ext/opcache/tests/opt/sccp_032.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions ext/standard/php_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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);
Expand Down
64 changes: 64 additions & 0 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include "scanf.h"
#include "zend_API.h"
#include "zend_execute.h"
#include "zend_string.h"
#include "php_globals.h"
#include "basic_functions.h"
#include "zend_smart_str.h"
#include <Zend/zend_exceptions.h>
Expand All @@ -50,6 +52,19 @@
#include "Zend/zend_bitset.h"
#endif

typedef struct {
char c;
const char *repr;
} char_repr_t;

static const char_repr_t char_reprs[] = {
{'\t', "\\t"},
{'\n', "\\n"},
{'\r', "\\r"},
{'"', "\\\""},
{'\\', "\\\\"},
};

/* this is read-only, so it's ok */
ZEND_SET_ALIGNED(16, static const char hexconvtab[]) = "0123456789abcdef";

Expand Down Expand Up @@ -3863,6 +3878,55 @@ PHPAPI zend_string *php_addcslashes_str(const char *str, size_t len, const char
}
/* }}} */

static const char *get_char_repr(char c) {
for (size_t i = 0; i < sizeof(char_reprs) / sizeof(char_reprs[0]); i++) {
if (char_reprs[i].c == c) {
return char_reprs[i].repr;
}
}
return NULL;
}

/* {{{ php_repr_str */
PHPAPI zend_string *php_repr_str(const char *str, size_t len) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, and I would also improve the naming. I don't find this particularly descriptive.

Copy link
Author

@WangYihang WangYihang Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any suggestions about the naming? basically this function take a string as input, returns a zend_string which converts all non-printable chars to a human readable format (e.g. chr(256) will be convert to "\xff").

The repr part in the function name was inspired by the python repr function which means REPResenting the STRing.

repr returns a string containing a printable representation of an object in Python.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function has the same output as smart_str_append_escaped() (minus the enclosing double quotes). Is there anything blocking us from using it?

size_t new_len = 0;
char *repr_str;

for (size_t i = 0; i < len; i++) {
const char *repr = get_char_repr(str[i]);
if (repr) {
new_len += strlen(repr);
} else if (isprint((unsigned char)str[i])) {
new_len += 1;
} else {
new_len += 4;
}
}

repr_str = emalloc(new_len + 1);

size_t pos = 0;
for (size_t i = 0; i < len; i++) {
const char *repr = get_char_repr(str[i]);
if (repr) {
size_t len_repr = strlen(repr);
memcpy(repr_str + pos, repr, len_repr);
pos += len_repr;
} else if (isprint((unsigned char)str[i])) {
repr_str[pos++] = str[i];
} else {
pos += snprintf(repr_str + pos, 5, "\\x%02x", (unsigned char)str[i]);
}
}

repr_str[pos] = '\0';
zend_string *zend_str = zend_string_init(repr_str, pos, 0);
efree(repr_str);

return zend_str;
}


/* {{{ php_addcslashes */
PHPAPI zend_string *php_addcslashes(zend_string *str, const char *what, size_t wlength)
{
Expand Down