Skip to content

Commit

Permalink
Make syslog() binary safe
Browse files Browse the repository at this point in the history
Closes GH-7245

Co-authored-by: Nikita Popov <nikita.ppv@googlemail.com>
  • Loading branch information
Girgias and nikic committed Jul 15, 2021
1 parent fae7cec commit 0ba155c
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 45 deletions.
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ PHP 8.1 UPGRADE NOTES
accessible through reflection.
RFC: https://wiki.php.net/rfc/make-reflection-setaccessible-no-op

- Standard:
. syslog() is now binary safe.

========================================
6. New Functions
========================================
Expand Down
7 changes: 3 additions & 4 deletions ext/standard/syslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,14 @@ PHP_FUNCTION(closelog)
PHP_FUNCTION(syslog)
{
zend_long priority;
char *message;
size_t message_len;
zend_string *message;

ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_LONG(priority)
Z_PARAM_STRING(message, message_len)
Z_PARAM_STR(message)
ZEND_PARSE_PARAMETERS_END();

php_syslog(priority, "%s", message);
php_syslog_str(priority, message);
RETURN_TRUE;
}
/* }}} */
Expand Down
19 changes: 19 additions & 0 deletions ext/standard/tests/network/syslog_new_line.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
Test syslog() function : new line in message
--SKIPIF--
<?php
if(substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--FILE--
<?php
$priority = LOG_WARNING;
$message = "First line\nSecond line";

openlog('PHPT', LOG_PERROR, LOG_USER);
syslog($priority, $message);

?>
--EXPECTF--
%SPHPT%S%r(:|-)%r First line
%SPHPT%S%r(:|-)%r Second line
18 changes: 18 additions & 0 deletions ext/standard/tests/network/syslog_null_byte.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
Test syslog() function : nul byte in message
--SKIPIF--
<?php
if(substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--FILE--
<?php
$priority = LOG_WARNING;
$message = "A simple \0 message";

openlog('PHPT', LOG_PERROR, LOG_USER);
syslog($priority, $message);

?>
--EXPECTF--
%SPHPT%S%r(:|-)%r A simple \x00 message
84 changes: 43 additions & 41 deletions main/php_syslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,45 @@
#define syslog std_syslog
#endif

PHPAPI void php_syslog_str(int priority, const zend_string* message)
{
smart_string sbuf = {0};

if (PG(syslog_filter) == PHP_SYSLOG_FILTER_RAW) {
/* Just send it directly to the syslog */
syslog(priority, "%s", ZSTR_VAL(message));
return;
}

/* We use < because we don't want the final NUL byte to be converted to '\x00' */
for (size_t i = 0; i < ZSTR_LEN(message); ++i) {
unsigned char c = ZSTR_VAL(message)[i];

/* check for NVT ASCII only unless test disabled */
if (((0x20 <= c) && (c <= 0x7e))) {
smart_string_appendc(&sbuf, c);
} else if ((c >= 0x80) && (PG(syslog_filter) != PHP_SYSLOG_FILTER_ASCII)) {
smart_string_appendc(&sbuf, c);
} else if (c == '\n') {
/* Smart string is not NUL terminated */
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
smart_string_reset(&sbuf);
} else if ((c < 0x20) && (PG(syslog_filter) == PHP_SYSLOG_FILTER_ALL)) {
smart_string_appendc(&sbuf, c);
} else {
const char xdigits[] = "0123456789abcdef";

smart_string_appendl(&sbuf, "\\x", 2);
smart_string_appendc(&sbuf, xdigits[c >> 4]);
smart_string_appendc(&sbuf, xdigits[c & 0xf]);
}
}

/* Smart string is not NUL terminated */
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
smart_string_free(&sbuf);
}

#ifdef PHP_WIN32
PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
{
Expand All @@ -54,10 +93,7 @@ PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
#else
PHPAPI void php_syslog(int priority, const char *format, ...) /* {{{ */
{
const char *ptr;
unsigned char c;
smart_string fbuf = {0};
smart_string sbuf = {0};
zend_string *fbuf = NULL;
va_list args;

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

va_start(args, format);
zend_printf_to_smart_string(&fbuf, format, args);
smart_string_0(&fbuf);
fbuf = zend_vstrpprintf(0, format, args);
va_end(args);

if (PG(syslog_filter) == PHP_SYSLOG_FILTER_RAW) {
/* Just send it directly to the syslog */
syslog(priority, "%.*s", (int)fbuf.len, fbuf.c);
smart_string_free(&fbuf);
return;
}

for (ptr = fbuf.c; ; ++ptr) {
c = *ptr;
if (c == '\0') {
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
break;
}

/* check for NVT ASCII only unless test disabled */
if (((0x20 <= c) && (c <= 0x7e)))
smart_string_appendc(&sbuf, c);
else if ((c >= 0x80) && (PG(syslog_filter) != PHP_SYSLOG_FILTER_ASCII))
smart_string_appendc(&sbuf, c);
else if (c == '\n') {
syslog(priority, "%.*s", (int)sbuf.len, sbuf.c);
smart_string_reset(&sbuf);
} else if ((c < 0x20) && (PG(syslog_filter) == PHP_SYSLOG_FILTER_ALL))
smart_string_appendc(&sbuf, c);
else {
const char xdigits[] = "0123456789abcdef";

smart_string_appendl(&sbuf, "\\x", 2);
smart_string_appendc(&sbuf, xdigits[(c / 0x10)]);
c &= 0x0f;
smart_string_appendc(&sbuf, xdigits[c]);
}
}
php_syslog_str(priority, fbuf);

smart_string_free(&fbuf);
smart_string_free(&sbuf);
zend_string_release(fbuf);
}
/* }}} */
#endif
1 change: 1 addition & 0 deletions main/php_syslog.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#define PHP_SYSLOG_FILTER_RAW 3

BEGIN_EXTERN_C()
PHPAPI void php_syslog_str(int priority, const zend_string* message);
PHPAPI void php_syslog(int, const char *format, ...);
PHPAPI void php_openlog(const char *, int, int);
END_EXTERN_C()
Expand Down

0 comments on commit 0ba155c

Please sign in to comment.