From 469fc770c1bc51a9a842786f0df8c53e52927cc6 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 26 Jul 2025 17:22:28 +0200 Subject: [PATCH] Fix GH-19248: Use strerror_r instead of strerror in main Closes GH-19251 --- main/network.c | 54 ++++++++++++++++++++++++++++++------ main/rfc1867.c | 3 +- main/streams/plain_wrapper.c | 46 ++++++++++++++++++++---------- main/streams/streams.c | 3 +- main/streams/xp_socket.c | 3 +- 5 files changed, 82 insertions(+), 27 deletions(-) diff --git a/main/network.c b/main/network.c index 8de81a6271a2f..dba1f6b6f218e 100644 --- a/main/network.c +++ b/main/network.c @@ -1061,16 +1061,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[256]; +# 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 +1109,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 +1118,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[256]; +# ifdef STRERROR_R_CHAR_P + char *errstr = strerror_r(err, ebuf, sizeof(ebuf)); +# else + const char *errstr; + errno_t res = strerror_r(err, buf, bufsize); + if (res == 0) { + errstr = buf; + } else { + errstr = "Unknown error"; + } +# endif +# else + char *errstr = strerror(err); +# endif return zend_string_init(errstr, strlen(errstr), 0); #else zend_string *ret; diff --git a/main/rfc1867.c b/main/rfc1867.c index cbdf8aaa07c5d..98efe1676d53a 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -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(errno, errstr, sizeof(errstr))); #endif cancel_upload = PHP_UPLOAD_ERROR_F; } else if (wlen < blen) { diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 1d5b7cfdac40d..41dccd55b66e7 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -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(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(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(errno, errstr, sizeof(errstr))); } return 0; } @@ -1321,6 +1327,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f } ret = VCWD_RENAME(url_from, url_to); + char errstr[256]; if (ret == -1) { #ifndef PHP_WIN32 @@ -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(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(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(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(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(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(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(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(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(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(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(errno, errstr, sizeof(errstr))); return 0; } fclose(file); @@ -1584,7 +1600,7 @@ 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(errno, errstr, sizeof(errstr))); return 0; } php_clear_stat_cache(0, NULL, 0); diff --git a/main/streams/streams.c b/main/streams/streams.c index 1471c98558e18..17b02d4779a50 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -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(errno, errstr, sizeof(errstr)); } else { msg = "operation failed"; } diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index b1d89bc44cb2b..c50d7fd8ad587 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -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(errno, errstr, sizeof(errstr))); } return -1; }