Skip to content

Commit 477c1d1

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 ca4a841 commit 477c1d1

File tree

6 files changed

+109
-27
lines changed

6 files changed

+109
-27
lines changed

main/network.c

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,27 @@ PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr)
10361036
}
10371037
/* }}} */
10381038

1039+
#ifdef PHP_WIN32
1040+
char *php_socket_strerror_s(long err, char *buf, size_t bufsize)
1041+
{
1042+
if (buf == NULL) {
1043+
char ebuf[1024];
1044+
errno_t res = strerror_s(ebuf, sizeof(ebuf), err);
1045+
if (res == 0) {
1046+
buf = estrdup(ebuf);
1047+
} else {
1048+
buf = estrdup("Unknown error");
1049+
}
1050+
} else {
1051+
errno_t res = strerror_s(buf, bufsize, err);
1052+
if (res != 0) {
1053+
strncpy(buf, "Unknown error", bufsize);
1054+
buf[bufsize?(bufsize-1):0] = 0;
1055+
}
1056+
}
1057+
}
1058+
#endif
1059+
10391060
/* Given a socket error code, if buf == NULL:
10401061
* emallocs storage for the error message and returns
10411062
* else
@@ -1045,16 +1066,40 @@ PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr)
10451066
PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
10461067
{
10471068
#ifndef PHP_WIN32
1048-
char *errstr;
1049-
1050-
errstr = strerror(err);
1069+
# ifdef HAVE_STRERROR_R
1070+
if (buf == NULL) {
1071+
char ebuf[1024];
1072+
# ifdef STRERROR_R_CHAR_P
1073+
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
1074+
buf = estrdup(errstr);
1075+
# else
1076+
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
1077+
if (res == 0) {
1078+
buf = estrdup(ebuf);
1079+
} else {
1080+
buf = estrdup("Unknown error");
1081+
}
1082+
# endif
1083+
} else {
1084+
# ifdef STRERROR_R_CHAR_P
1085+
buf = strerror_r(err, buf, bufsize);
1086+
# else
1087+
errno_t res = strerror_r(err, buf, bufsize);
1088+
if (res != 0) {
1089+
strncpy(buf, "Unknown error", bufsize);
1090+
buf[bufsize?(bufsize-1):0] = 0;
1091+
}
1092+
# endif
1093+
}
1094+
# else
1095+
char *errstr = strerror(err);
10511096
if (buf == NULL) {
10521097
buf = estrdup(errstr);
10531098
} else {
10541099
strncpy(buf, errstr, bufsize);
10551100
buf[bufsize?(bufsize-1):0] = 0;
10561101
}
1057-
return buf;
1102+
# endif
10581103
#else
10591104
char *sysbuf = php_win32_error_to_msg(err);
10601105
if (!sysbuf[0]) {
@@ -1069,19 +1114,31 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
10691114
}
10701115

10711116
php_win32_error_msg_free(sysbuf);
1072-
1073-
return buf;
10741117
#endif
1118+
return buf;
10751119
}
10761120
/* }}} */
10771121

10781122
/* {{{ php_socket_error_str */
10791123
PHPAPI zend_string *php_socket_error_str(long err)
10801124
{
10811125
#ifndef PHP_WIN32
1082-
char *errstr;
1083-
1084-
errstr = strerror(err);
1126+
# ifdef HAVE_STRERROR_R
1127+
char ebuf[1024];
1128+
# ifdef STRERROR_R_CHAR_P
1129+
char *errstr = strerror_r(err, ebuf, sizeof(ebuf));
1130+
# else
1131+
const char *errstr;
1132+
errno_t res = strerror_r(err, ebuf, sizeof(ebuf));
1133+
if (res == 0) {
1134+
errstr = ebuf;
1135+
} else {
1136+
errstr = "Unknown error";
1137+
}
1138+
# endif
1139+
# else
1140+
char *errstr = strerror(err);
1141+
# endif
10851142
return zend_string_init(errstr, strlen(errstr), 0);
10861143
#else
10871144
zend_string *ret;

main/php_network.h

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

main/rfc1867.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
10481048
if (wlen == (size_t)-1) {
10491049
/* write failed */
10501050
#if DEBUG_FILE_UPLOAD
1051-
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno));
1051+
char errstr[256];
1052+
sapi_module.sapi_error(E_NOTICE, "write() failed - %s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
10521053
#endif
10531054
cancel_upload = PHP_UPLOAD_ERROR_F;
10541055
} else if (wlen < blen) {

main/streams/plain_wrapper.c

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

449453
/* TODO: Remove this special-case? */
@@ -1257,7 +1261,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url,
12571261
ret = VCWD_UNLINK(url);
12581262
if (ret == -1) {
12591263
if (options & REPORT_ERRORS) {
1260-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1264+
char errstr[256];
1265+
php_error_docref1(NULL, url, E_WARNING, "%s",
1266+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
12611267
}
12621268
return 0;
12631269
}
@@ -1300,6 +1306,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13001306
}
13011307

13021308
ret = VCWD_RENAME(url_from, url_to);
1309+
char errstr[256];
13031310

13041311
if (ret == -1) {
13051312
#ifndef PHP_WIN32
@@ -1323,15 +1330,17 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13231330
* access to the file in the meantime.
13241331
*/
13251332
if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
1326-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1333+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1334+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13271335
if (errno != EPERM) {
13281336
success = 0;
13291337
}
13301338
}
13311339

13321340
if (success) {
13331341
if (VCWD_CHMOD(url_to, sb.st_mode)) {
1334-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1342+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1343+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13351344
if (errno != EPERM) {
13361345
success = 0;
13371346
}
@@ -1342,10 +1351,12 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13421351
VCWD_UNLINK(url_from);
13431352
}
13441353
} else {
1345-
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)));
13461356
}
13471357
} else {
1348-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1358+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1359+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13491360
}
13501361
# if !defined(ZTS) && !defined(TSRM_WIN32)
13511362
umask(oldmask);
@@ -1358,7 +1369,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
13581369
#ifdef PHP_WIN32
13591370
php_win32_docref2_from_error(GetLastError(), url_from, url_to);
13601371
#else
1361-
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno));
1372+
php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s",
1373+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
13621374
#endif
13631375
return 0;
13641376
}
@@ -1438,11 +1450,12 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
14381450
if (!p) {
14391451
p = buf;
14401452
}
1453+
char errstr[256];
14411454
while (true) {
14421455
int ret = VCWD_MKDIR(buf, (mode_t) mode);
14431456
if (ret < 0 && errno != EEXIST) {
14441457
if (options & REPORT_ERRORS) {
1445-
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1458+
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
14461459
}
14471460
return 0;
14481461
}
@@ -1462,7 +1475,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
14621475
/* issue a warning to client when the last directory was created failed */
14631476
if (ret < 0) {
14641477
if (options & REPORT_ERRORS) {
1465-
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1478+
php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
14661479
}
14671480
return 0;
14681481
}
@@ -1481,15 +1494,16 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i
14811494
return 0;
14821495
}
14831496

1497+
char errstr[256];
14841498
#ifdef PHP_WIN32
14851499
if (!php_win32_check_trailing_space(url, strlen(url))) {
1486-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1500+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
14871501
return 0;
14881502
}
14891503
#endif
14901504

14911505
if (VCWD_RMDIR(url) < 0) {
1492-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno));
1506+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr)));
14931507
return 0;
14941508
}
14951509

@@ -1508,10 +1522,11 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15081522
#endif
15091523
mode_t mode;
15101524
int ret = 0;
1525+
char errstr[256];
15111526

15121527
#ifdef PHP_WIN32
15131528
if (!php_win32_check_trailing_space(url, strlen(url))) {
1514-
php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT));
1529+
php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr)));
15151530
return 0;
15161531
}
15171532
#endif
@@ -1530,7 +1545,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15301545
if (VCWD_ACCESS(url, F_OK) != 0) {
15311546
FILE *file = VCWD_FOPEN(url, "w");
15321547
if (file == NULL) {
1533-
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno));
1548+
php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url,
1549+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
15341550
return 0;
15351551
}
15361552
fclose(file);
@@ -1573,7 +1589,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
15731589
return 0;
15741590
}
15751591
if (ret == -1) {
1576-
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno));
1592+
php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s",
1593+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
15771594
return 0;
15781595
}
15791596
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
@@ -204,7 +204,8 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const
204204
free_msg = 1;
205205
} else {
206206
if (wrapper == &php_plain_files_wrapper) {
207-
msg = strerror(errno); /* TODO: not ts on linux */
207+
char errstr[256];
208+
msg = php_socket_strerror_s(errno, errstr, sizeof(errstr));
208209
} else {
209210
msg = "operation failed";
210211
}

main/streams/xp_socket.c

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

679679
if (sock->socket == SOCK_ERR) {
680680
if (xparam->want_errortext) {
681+
char errstr[256];
681682
xparam->outputs.error_text = strpprintf(0, "Failed to create unix%s socket %s",
682683
stream->ops == &php_stream_unix_socket_ops ? "" : "datagram",
683-
strerror(errno));
684+
php_socket_strerror_s(errno, errstr, sizeof(errstr)));
684685
}
685686
return -1;
686687
}

0 commit comments

Comments
 (0)