Skip to content

Commit d6b94ac

Browse files
committed
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
1 parent 96c0bc5 commit d6b94ac

File tree

6 files changed

+110
-27
lines changed

6 files changed

+110
-27
lines changed

main/network.c

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,28 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
10521052
}
10531053
/* }}} */
10541054

1055+
#ifdef PHP_WIN32
1056+
char *php_socket_strerror_s(long err, char *buf, size_t bufsize)
1057+
{
1058+
if (buf == NULL) {
1059+
char ebuf[1024];
1060+
errno_t res = strerror_s(ebuf, sizeof(ebuf), err);
1061+
if (res == 0) {
1062+
buf = estrdup(ebuf);
1063+
} else {
1064+
buf = estrdup("Unknown error");
1065+
}
1066+
} else {
1067+
errno_t res = strerror_s(buf, bufsize, err);
1068+
if (res != 0) {
1069+
strncpy(buf, "Unknown error", bufsize);
1070+
buf[bufsize?(bufsize-1):0] = 0;
1071+
}
1072+
}
1073+
return buf;
1074+
}
1075+
#endif
1076+
10551077
/* Given a socket error code, if buf == NULL:
10561078
* emallocs storage for the error message and returns
10571079
* else
@@ -1061,16 +1083,40 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
10611083
PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
10621084
{
10631085
#ifndef PHP_WIN32
1064-
char *errstr;
1065-
1066-
errstr = strerror(err);
1086+
# ifdef HAVE_STRERROR_R
1087+
if (buf == NULL) {
1088+
char ebuf[1024];
1089+
# ifdef STRERROR_R_CHAR_P
1090+
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
1091+
buf = estrdup(errstr);
1092+
# else
1093+
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
1094+
if (res == 0) {
1095+
buf = estrdup(ebuf);
1096+
} else {
1097+
buf = estrdup("Unknown error");
1098+
}
1099+
# endif
1100+
} else {
1101+
# ifdef STRERROR_R_CHAR_P
1102+
buf = strerror_r(err, buf, bufsize);
1103+
# else
1104+
errno_t res = strerror_r(err, buf, bufsize);
1105+
if (res != 0) {
1106+
strncpy(buf, "Unknown error", bufsize);
1107+
buf[bufsize?(bufsize-1):0] = 0;
1108+
}
1109+
# endif
1110+
}
1111+
# else
1112+
char *errstr = strerror(err);
10671113
if (buf == NULL) {
10681114
buf = estrdup(errstr);
10691115
} else {
10701116
strncpy(buf, errstr, bufsize);
10711117
buf[bufsize?(bufsize-1):0] = 0;
10721118
}
1073-
return buf;
1119+
# endif
10741120
#else
10751121
char *sysbuf = php_win32_error_to_msg(err);
10761122
if (!sysbuf[0]) {
@@ -1085,19 +1131,31 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
10851131
}
10861132

10871133
php_win32_error_msg_free(sysbuf);
1088-
1089-
return buf;
10901134
#endif
1135+
return buf;
10911136
}
10921137
/* }}} */
10931138

10941139
/* {{{ php_socket_error_str */
10951140
PHPAPI zend_string *php_socket_error_str(long err)
10961141
{
10971142
#ifndef PHP_WIN32
1098-
char *errstr;
1099-
1100-
errstr = strerror(err);
1143+
# ifdef HAVE_STRERROR_R
1144+
char ebuf[1024];
1145+
# ifdef STRERROR_R_CHAR_P
1146+
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
1147+
# else
1148+
const char *errstr;
1149+
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
1150+
if (res == 0) {
1151+
errstr = ebuf;
1152+
} else {
1153+
errstr = "Unknown error";
1154+
}
1155+
# endif
1156+
# else
1157+
char *errstr = strerror(err);
1158+
# endif
11011159
return zend_string_init(errstr, strlen(errstr), 0);
11021160
#else
11031161
zend_string *ret;

main/php_network.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@
6666
* unless buf is not NULL.
6767
* Also works sensibly for win32 */
6868
BEGIN_EXTERN_C()
69+
#ifdef PHP_WIN32
70+
char *php_socket_strerror_s(long err, char *buf, size_t bufsize);
71+
#else
72+
#define php_socket_strerror_s php_socket_strerror
73+
#endif
6974
PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize);
7075
PHPAPI zend_string *php_socket_error_str(long err);
7176
END_EXTERN_C()

main/rfc1867.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */
10381038
if (wlen == (size_t)-1) {
10391039
/* write failed */
10401040
#if DEBUG_FILE_UPLOAD
1041-
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
1041+
char errstr[256];
1042+
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
10421043
#endif
10431044
cancel_upload = PHP_UPLOAD_ERROR_F;
10441045
} else if (wlen < blen) {

main/streams/plain_wrapper.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,9 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
368368
return bytes_written;
369369
}
370370
if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
371-
php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
371+
char errstr[256];
372+
php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s",
373+
count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr)));
372374
}
373375
}
374376
} else {
@@ -444,7 +446,9 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
444446
/* TODO: Should this be treated as a proper error or not? */
445447
} else {
446448
if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) {
447-
php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
449+
char errstr[256];
450+
php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s",
451+
count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr)));
448452
}
449453

450454
/* TODO: Remove this special-case? */
@@ -1278,7 +1282,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url,
12781282
ret = VCWD_UNLINK(url);
12791283
if (ret == -1) {
12801284
if (options & REPORT_ERRORS) {
1281-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1285+
char errstr[256];
1286+
php_error_docref1(NULL, url, E_WARNING, "%s",
1287+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
12821288
}
12831289
return 0;
12841290
}
@@ -1324,6 +1330,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13241330

13251331
if (ret == -1) {
13261332
#ifndef PHP_WIN32
1333+
char errstr[256];
13271334
# ifdef EXDEV
13281335
if (errno == EXDEV) {
13291336
zend_stat_t sb;
@@ -1344,15 +1351,17 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13441351
* access to the file in the meantime.
13451352
*/
13461353
if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
1347-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1354+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1355+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13481356
if (errno != EPERM) {
13491357
success = 0;
13501358
}
13511359
}
13521360

13531361
if (success) {
13541362
if (VCWD_CHMOD(url_to, sb.st_mode)) {
1355-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1363+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1364+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13561365
if (errno != EPERM) {
13571366
success = 0;
13581367
}
@@ -1363,10 +1372,12 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13631372
VCWD_UNLINK(url_from);
13641373
}
13651374
} else {
1366-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1375+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1376+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13671377
}
13681378
} else {
1369-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1379+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1380+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13701381
}
13711382
# if !defined(ZTS) && !defined(TSRM_WIN32)
13721383
umask(oldmask);
@@ -1379,7 +1390,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13791390
#ifdef PHP_WIN32
13801391
php_win32_docref2_from_error(GetLastError(), url_from, url_to);
13811392
#else
1382-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1393+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1394+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13831395
#endif
13841396
return 0;
13851397
}
@@ -1449,11 +1461,12 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
14491461
if (!p) {
14501462
p = buf;
14511463
}
1464+
char errstr[256];
14521465
while (true) {
14531466
int ret = VCWD_MKDIR(buf, (mode_t) mode);
14541467
if (ret < 0 && errno != EEXIST) {
14551468
if (options & REPORT_ERRORS) {
1456-
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1469+
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
14571470
}
14581471
return 0;
14591472
}
@@ -1473,7 +1486,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
14731486
/* issue a warning to client when the last directory was created failed */
14741487
if (ret < 0) {
14751488
if (options & REPORT_ERRORS) {
1476-
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1489+
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
14771490
}
14781491
return 0;
14791492
}
@@ -1492,15 +1505,16 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i
14921505
return 0;
14931506
}
14941507

1508+
char errstr[256];
14951509
#ifdef PHP_WIN32
14961510
if (!php_win32_check_trailing_space(url, strlen(url))) {
1497-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1511+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
14981512
return 0;
14991513
}
15001514
#endif
15011515

15021516
if (VCWD_RMDIR(url) < 0) {
1503-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1517+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
15041518
return 0;
15051519
}
15061520

@@ -1519,10 +1533,11 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15191533
#endif
15201534
mode_t mode;
15211535
int ret = 0;
1536+
char errstr[256];
15221537

15231538
#ifdef PHP_WIN32
15241539
if (!php_win32_check_trailing_space(url, strlen(url))) {
1525-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1540+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
15261541
return 0;
15271542
}
15281543
#endif
@@ -1541,7 +1556,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15411556
if (VCWD_ACCESS(url, F_OK) != 0) {
15421557
FILE *file = VCWD_FOPEN(url, "w");
15431558
if (file == NULL) {
1544-
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno));
1559+
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url,
1560+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
15451561
return 0;
15461562
}
15471563
fclose(file);
@@ -1584,7 +1600,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15841600
return 0;
15851601
}
15861602
if (ret == -1) {
1587-
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno));
1603+
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s",
1604+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
15881605
return 0;
15891606
}
15901607
php_clear_stat_cache(0, NULL, 0);

main/streams/streams.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const
203203
free_msg = 1;
204204
} else {
205205
if (wrapper == &php_plain_files_wrapper) {
206-
msg = strerror(errno); /* TODO: not ts on linux */
206+
char errstr[256];
207+
msg = php_socket_strerror_s(errno, errstr, sizeof(errstr));
207208
} else {
208209
msg = "operation failed";
209210
}

main/streams/xp_socket.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,10 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *
674674

675675
if (sock->socket == SOCK_ERR) {
676676
if (xparam->want_errortext) {
677+
char errstr[256];
677678
xparam->outputs.error_text = strpprintf(0, "Failed to create unix%s socket %s",
678679
stream->ops == &php_stream_unix_socket_ops ? "" : "datagram",
679-
strerror(errno));
680+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
680681
}
681682
return -1;
682683
}

0 commit comments

Comments
 (0)