Skip to content

Enhance zend_dump_op_array to Properly Represent Non-Printable Characters (GH-15680) #15730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 2 additions & 4 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);

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));
Comment on lines -70 to +71
Copy link
Member

@arnaud-lb arnaud-lb Sep 9, 2024

Choose a reason for hiding this comment

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

We can achieve a similar result with php_addcslashes(Z_STR_P(zv), "\x00..\x1f\\\\\x7f..\xff", 10) (with the difference that it uses an octal representation), or the same result with smart_str_append_escaped().

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\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")
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
284 changes: 284 additions & 0 deletions ext/standard/charrepr.h
Original file line number Diff line number Diff line change
@@ -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 <wangyihanger@gmail.com> |
+----------------------------------------------------------------------+
*/

#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] = {
Copy link
Member

Choose a reason for hiding this comment

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

What is the reason to separate this array into a header?
It's going to be duplicated every time the header is included.

Copy link
Author

Choose a reason for hiding this comment

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

The reason I separated this array into a header file was primarily for modularity and reusability.

The current file (string.c) is already quite long, and combining these contents with the C file might make it harder to read and maintain.

However, if you believe this separation is unnecessary, I can certainly move this part back into string.c.

Copy link
Member

Choose a reason for hiding this comment

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

Was this code copied from somewhere? There's no header/license that would indicate so.

{"\\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
1 change: 1 addition & 0 deletions ext/standard/php_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading