Skip to content

Commit 0ba155c

Browse files
Girgiasnikic
andcommitted
Make syslog() binary safe
Closes phpGH-7245 Co-authored-by: Nikita Popov <[email protected]>
1 parent fae7cec commit 0ba155c

File tree

6 files changed

+87
-45
lines changed

6 files changed

+87
-45
lines changed

UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@ PHP 8.1 UPGRADE NOTES
471471
accessible through reflection.
472472
RFC: https://wiki.php.net/rfc/make-reflection-setaccessible-no-op
473473

474+
- Standard:
475+
. syslog() is now binary safe.
476+
474477
========================================
475478
6. New Functions
476479
========================================

ext/standard/syslog.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,14 @@ PHP_FUNCTION(closelog)
174174
PHP_FUNCTION(syslog)
175175
{
176176
zend_long priority;
177-
char *message;
178-
size_t message_len;
177+
zend_string *message;
179178

180179
ZEND_PARSE_PARAMETERS_START(2, 2)
181180
Z_PARAM_LONG(priority)
182-
Z_PARAM_STRING(message, message_len)
181+
Z_PARAM_STR(message)
183182
ZEND_PARSE_PARAMETERS_END();
184183

185-
php_syslog(priority, "%s", message);
184+
php_syslog_str(priority, message);
186185
RETURN_TRUE;
187186
}
188187
/* }}} */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Test syslog() function : new line in message
3+
--SKIPIF--
4+
<?php
5+
if(substr(PHP_OS, 0, 3) == "WIN")
6+
die("skip Won't run on Windows");
7+
?>
8+
--FILE--
9+
<?php
10+
$priority = LOG_WARNING;
11+
$message = "First line\nSecond line";
12+
13+
openlog('PHPT', LOG_PERROR, LOG_USER);
14+
syslog($priority, $message);
15+
16+
?>
17+
--EXPECTF--
18+
%SPHPT%S%r(:|-)%r First line
19+
%SPHPT%S%r(:|-)%r Second line
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Test syslog() function : nul byte in message
3+
--SKIPIF--
4+
<?php
5+
if(substr(PHP_OS, 0, 3) == "WIN")
6+
die("skip Won't run on Windows");
7+
?>
8+
--FILE--
9+
<?php
10+
$priority = LOG_WARNING;
11+
$message = "A simple \0 message";
12+
13+
openlog('PHPT', LOG_PERROR, LOG_USER);
14+
syslog($priority, $message);
15+
16+
?>
17+
--EXPECTF--
18+
%SPHPT%S%r(:|-)%r A simple \x00 message

main/php_syslog.c

+43-41
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,45 @@
3232
#define syslog std_syslog
3333
#endif
3434

35+
PHPAPI void php_syslog_str(int priority, const zend_string* message)
36+
{
37+
smart_string sbuf = {0};
38+
39+
if (PG(syslog_filter) == PHP_SYSLOG_FILTER_RAW) {
40+
/* Just send it directly to the syslog */
41+
syslog(priority, "%s", ZSTR_VAL(message));
42+
return;
43+
}
44+
45+
/* We use < because we don't want the final NUL byte to be converted to '\x00' */
46+
for (size_t i = 0; i < ZSTR_LEN(message); ++i) {
47+
unsigned char c = ZSTR_VAL(message)[i];
48+
49+
/* check for NVT ASCII only unless test disabled */
50+
if (((0x20 <= c) && (c <= 0x7e))) {
51+
smart_string_appendc(&sbuf, c);
52+
} else if ((c >= 0x80) && (PG(syslog_filter) != PHP_SYSLOG_FILTER_ASCII)) {
53+
smart_string_appendc(&sbuf, c);
54+
} else if (c == '\n') {
55+
/* Smart string is not NUL terminated */
56+
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
57+
smart_string_reset(&sbuf);
58+
} else if ((c < 0x20) && (PG(syslog_filter) == PHP_SYSLOG_FILTER_ALL)) {
59+
smart_string_appendc(&sbuf, c);
60+
} else {
61+
const char xdigits[] = "0123456789abcdef";
62+
63+
smart_string_appendl(&sbuf, "\\x", 2);
64+
smart_string_appendc(&sbuf, xdigits[c >> 4]);
65+
smart_string_appendc(&sbuf, xdigits[c & 0xf]);
66+
}
67+
}
68+
69+
/* Smart string is not NUL terminated */
70+
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
71+
smart_string_free(&sbuf);
72+
}
73+
3574
#ifdef PHP_WIN32
3675
PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
3776
{
@@ -54,10 +93,7 @@ PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
5493
#else
5594
PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
5695
{
57-
const char *ptr;
58-
unsigned char c;
59-
smart_string fbuf = {0};
60-
smart_string sbuf = {0};
96+
zend_string *fbuf = NULL;
6197
va_list args;
6298

6399
/*
@@ -70,46 +106,12 @@ PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
70106
}
71107

72108
va_start(args, format);
73-
zend_printf_to_smart_string(&fbuf, format, args);
74-
smart_string_0(&fbuf);
109+
fbuf = zend_vstrpprintf(0, format, args);
75110
va_end(args);
76111

77-
if (PG(syslog_filter) == PHP_SYSLOG_FILTER_RAW) {
78-
/* Just send it directly to the syslog */
79-
syslog(priority, "%.*s", (int)fbuf.len, fbuf.c);
80-
smart_string_free(&fbuf);
81-
return;
82-
}
83-
84-
for (ptr = fbuf.c; ; ++ptr) {
85-
c = *ptr;
86-
if (c == '\0') {
87-
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
88-
break;
89-
}
90-
91-
/* check for NVT ASCII only unless test disabled */
92-
if (((0x20 <= c) && (c <= 0x7e)))
93-
smart_string_appendc(&sbuf, c);
94-
else if ((c >= 0x80) && (PG(syslog_filter) != PHP_SYSLOG_FILTER_ASCII))
95-
smart_string_appendc(&sbuf, c);
96-
else if (c == '\n') {
97-
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
98-
smart_string_reset(&sbuf);
99-
} else if ((c < 0x20) && (PG(syslog_filter) == PHP_SYSLOG_FILTER_ALL))
100-
smart_string_appendc(&sbuf, c);
101-
else {
102-
const char xdigits[] = "0123456789abcdef";
103-
104-
smart_string_appendl(&sbuf, "\\x", 2);
105-
smart_string_appendc(&sbuf, xdigits[(c / 0x10)]);
106-
c &= 0x0f;
107-
smart_string_appendc(&sbuf, xdigits[c]);
108-
}
109-
}
112+
php_syslog_str(priority, fbuf);
110113

111-
smart_string_free(&fbuf);
112-
smart_string_free(&sbuf);
114+
zend_string_release(fbuf);
113115
}
114116
/* }}} */
115117
#endif

main/php_syslog.h

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#define PHP_SYSLOG_FILTER_RAW 3
3636

3737
BEGIN_EXTERN_C()
38+
PHPAPI void php_syslog_str(int priority, const zend_string* message);
3839
PHPAPI void php_syslog(int, const char *format, ...);
3940
PHPAPI void php_openlog(const char *, int, int);
4041
END_EXTERN_C()

0 commit comments

Comments
 (0)