1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-19248: Use strerror_r instead of strerror in main

Or on Windows it is going to use either FormatMessageW or strerror_s
for compatibility with previous error messages.

It also needs to accomodate for GNU and BSD versions of strerror_r
returning different type.

Closes GH-19251
This commit is contained in:
Jakub Zelenka
2025-07-26 17:22:28 +02:00
parent 7c859268c0
commit b7fdfb7147
7 changed files with 114 additions and 27 deletions

4
NEWS
View File

@@ -52,6 +52,10 @@ PHP NEWS
. Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()).
(alexandre-daubois)
- Streams:
. Fixed bug GH-19248 (Use strerror_r instead of strerror in main).
(Jakub Zelenka)
- XMLReader:
. Fixed bug GH-20009 (XMLReader leak on RelaxNG schema failure). (nielsdos)

View File

@@ -1052,6 +1052,28 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
}
/* }}} */
#ifdef PHP_WIN32
char *php_socket_strerror_s(long err, char *buf, size_t bufsize)
{
if (buf == NULL) {
char ebuf[1024];
errno_t res = strerror_s(ebuf, sizeof(ebuf), err);
if (res == 0) {
buf = estrdup(ebuf);
} else {
buf = estrdup("Unknown error");
}
} else {
errno_t res = strerror_s(buf, bufsize, err);
if (res != 0) {
strncpy(buf, "Unknown error", bufsize);
buf[bufsize?(bufsize-1):0] = 0;
}
}
return buf;
}
#endif
/* Given a socket error code, if buf == NULL:
* emallocs storage for the error message and returns
* else
@@ -1061,16 +1083,40 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
{
#ifndef PHP_WIN32
char *errstr;
errstr = strerror(err);
# ifdef HAVE_STRERROR_R
if (buf == NULL) {
char ebuf[1024];
# ifdef STRERROR_R_CHAR_P
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
buf = estrdup(errstr);
# else
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
if (res == 0) {
buf = estrdup(ebuf);
} else {
buf = estrdup("Unknown error");
}
# endif
} else {
# ifdef STRERROR_R_CHAR_P
buf = strerror_r(err, buf, bufsize);
# else
errno_t res = strerror_r(err, buf, bufsize);
if (res != 0) {
strncpy(buf, "Unknown error", bufsize);
buf[bufsize?(bufsize-1):0] = 0;
}
# endif
}
# else
char *errstr = strerror(err);
if (buf == NULL) {
buf = estrdup(errstr);
} else {
strncpy(buf, errstr, bufsize);
buf[bufsize?(bufsize-1):0] = 0;
}
return buf;
# endif
#else
char *sysbuf = php_win32_error_to_msg(err);
if (!sysbuf[0]) {
@@ -1085,9 +1131,8 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
}
php_win32_error_msg_free(sysbuf);
return buf;
#endif
return buf;
}
/* }}} */
@@ -1095,9 +1140,22 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
PHPAPI zend_string *php_socket_error_str(long err)
{
#ifndef PHP_WIN32
char *errstr;
errstr = strerror(err);
# ifdef HAVE_STRERROR_R
char ebuf[1024];
# ifdef STRERROR_R_CHAR_P
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
# else
const char *errstr;
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
if (res == 0) {
errstr = ebuf;
} else {
errstr = "Unknown error";
}
# endif
# else
char *errstr = strerror(err);
# endif
return zend_string_init(errstr, strlen(errstr), 0);
#else
zend_string *ret;

View File

@@ -66,6 +66,11 @@
* unless buf is not NULL.
* Also works sensibly for win32 */
BEGIN_EXTERN_C()
#ifdef PHP_WIN32
char *php_socket_strerror_s(long err, char *buf, size_t bufsize);
#else
#define php_socket_strerror_s php_socket_strerror
#endif
PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize);
PHPAPI zend_string *php_socket_error_str(long err);
END_EXTERN_C()

View File

@@ -1038,7 +1038,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
if (wlen == (size_t)-1) {
/* write failed */
#if DEBUG_FILE_UPLOAD
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
char errstr[256];
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
#endif
cancel_upload = PHP_UPLOAD_ERROR_F;
} else if (wlen < blen) {

View File

@@ -368,7 +368,9 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
return bytes_written;
}
if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
char errstr[256];
php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s",
count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
}
} else {
@@ -444,7 +446,9 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
/* TODO: Should this be treated as a proper error or not? */
} else {
if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
char errstr[256];
php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s",
count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
/* TODO: Remove this special-case? */
@@ -1278,7 +1282,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url,
ret = VCWD_UNLINK(url);
if (ret == -1) {
if (options & REPORT_ERRORS) {
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
char errstr[256];
php_error_docref1(NULL, url, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
return 0;
}
@@ -1324,6 +1330,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
if (ret == -1) {
#ifndef PHP_WIN32
char errstr[256];
# ifdef EXDEV
if (errno == EXDEV) {
zend_stat_t sb;
@@ -1344,7 +1351,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
* access to the file in the meantime.
*/
if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
if (errno != EPERM) {
success = 0;
}
@@ -1352,7 +1360,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
if (success) {
if (VCWD_CHMOD(url_to, sb.st_mode)) {
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
if (errno != EPERM) {
success = 0;
}
@@ -1363,10 +1372,12 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
VCWD_UNLINK(url_from);
}
} else {
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
} else {
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
# if !defined(ZTS) && !defined(TSRM_WIN32)
umask(oldmask);
@@ -1379,7 +1390,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
#ifdef PHP_WIN32
php_win32_docref2_from_error(GetLastError(), url_from, url_to);
#else
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
#endif
return 0;
}
@@ -1449,11 +1461,12 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
if (!p) {
p = buf;
}
char errstr[256];
while (true) {
int ret = VCWD_MKDIR(buf, (mode_t) mode);
if (ret < 0 && errno != EEXIST) {
if (options & REPORT_ERRORS) {
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
return 0;
}
@@ -1473,7 +1486,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
/* issue a warning to client when the last directory was created failed */
if (ret < 0) {
if (options & REPORT_ERRORS) {
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
return 0;
}
@@ -1492,15 +1505,16 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i
return 0;
}
char errstr[256];
#ifdef PHP_WIN32
if (!php_win32_check_trailing_space(url, strlen(url))) {
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
return 0;
}
#endif
if (VCWD_RMDIR(url) < 0) {
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
return 0;
}
@@ -1519,10 +1533,11 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
#endif
mode_t mode;
int ret = 0;
char errstr[256];
#ifdef PHP_WIN32
if (!php_win32_check_trailing_space(url, strlen(url))) {
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
return 0;
}
#endif
@@ -1541,7 +1556,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
if (VCWD_ACCESS(url, F_OK) != 0) {
FILE *file = VCWD_FOPEN(url, "w");
if (file == NULL) {
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno));
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url,
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
return 0;
}
fclose(file);
@@ -1584,7 +1600,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
return 0;
}
if (ret == -1) {
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno));
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s",
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
return 0;
}
php_clear_stat_cache(0, NULL, 0);

View File

@@ -203,7 +203,8 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const
free_msg = 1;
} else {
if (wrapper == &php_plain_files_wrapper) {
msg = strerror(errno); /* TODO: not ts on linux */
char errstr[256];
msg = php_socket_strerror_s(errno, errstr, sizeof(errstr));
} else {
msg = "operation failed";
}

View File

@@ -674,9 +674,10 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *
if (sock->socket == SOCK_ERR) {
if (xparam->want_errortext) {
char errstr[256];
xparam->outputs.error_text = strpprintf(0, "Failed to create unix%s socket %s",
stream->ops == &php_stream_unix_socket_ops ? "" : "datagram",
strerror(errno));
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
}
return -1;
}