Skip to content

Commit 2ae036f

Browse files
author
Ilia Alshanetsky
committed
Fixed bug #40098 (php_fopen_primary_script() not thread safe). Adjusted previous fixes for similar issue to handle sysconf() failures
1 parent ed30473 commit 2ae036f

File tree

5 files changed

+74
-33
lines changed

5 files changed

+74
-33
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ PHP NEWS
44
- Added CURLOPT_TCP_NODELAY constant to Curl extension. (Sara)
55
- Improved proc_open(). Now on Windows it can run external commands not through
66
CMD.EXE. (Dmitry)
7+
- Fixed bug #40098 (php_fopen_primary_script() not thread safe). (Ilia)
78
- Fixed bug #40091 (spl_autoload_register with 2 instances of the same
89
class). (Ilia)
910
- Fixed bug #40083 (milter SAPI functions always return false/null). (Tony)

ext/posix/posix.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,8 @@ PHP_FUNCTION(posix_ttyname)
555555
zval **z_fd;
556556
char *p;
557557
int fd;
558-
#if HAVE_TTYNAME_R
559-
size_t buflen;
558+
#if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
559+
long buflen;
560560
#endif
561561

562562
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &z_fd) == FAILURE) {
@@ -573,8 +573,11 @@ PHP_FUNCTION(posix_ttyname)
573573
convert_to_long_ex(z_fd);
574574
fd = Z_LVAL_PP(z_fd);
575575
}
576-
#if HAVE_TTYNAME_R
576+
#if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
577577
buflen = sysconf(_SC_TTY_NAME_MAX);
578+
if (buflen < 1) {
579+
RETURN_FALSE;
580+
}
578581
p = emalloc(buflen);
579582

580583
if (ttyname_r(fd, p, buflen)) {
@@ -822,18 +825,21 @@ PHP_FUNCTION(posix_getgrnam)
822825
char *name;
823826
struct group *g;
824827
int name_len;
825-
#if HAVE_GETGRNAM_R
828+
#if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
826829
struct group gbuf;
827-
int buflen;
830+
long buflen;
828831
char *buf;
829832
#endif
830833

831834
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
832835
RETURN_FALSE;
833836
}
834837

835-
#if HAVE_GETGRNAM_R
838+
#if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
836839
buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
840+
if (buflen < 1) {
841+
RETURN_FALSE;
842+
}
837843
buf = emalloc(buflen);
838844
g = &gbuf;
839845

@@ -855,7 +861,7 @@ PHP_FUNCTION(posix_getgrnam)
855861
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix group to array");
856862
RETVAL_FALSE;
857863
}
858-
#if HAVE_GETGRNAM_R
864+
#if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
859865
efree(buf);
860866
#endif
861867
}
@@ -870,7 +876,7 @@ PHP_FUNCTION(posix_getgrgid)
870876
int ret;
871877
struct group _g;
872878
struct group *retgrptr;
873-
int grbuflen;
879+
long grbuflen;
874880
char *grbuf;
875881
#endif
876882
struct group *g;
@@ -932,18 +938,21 @@ PHP_FUNCTION(posix_getpwnam)
932938
struct passwd *pw;
933939
char *name;
934940
int name_len;
935-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
941+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
936942
struct passwd pwbuf;
937-
int buflen;
943+
long buflen;
938944
char *buf;
939945
#endif
940946

941947
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
942948
RETURN_FALSE;
943949
}
944950

945-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
951+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
946952
buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
953+
if (buflen < 1) {
954+
RETURN_FALSE;
955+
}
947956
buf = emalloc(buflen);
948957
pw = &pwbuf;
949958

@@ -965,7 +974,7 @@ PHP_FUNCTION(posix_getpwnam)
965974
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
966975
RETVAL_FALSE;
967976
}
968-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
977+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
969978
efree(buf);
970979
#endif
971980
}
@@ -976,10 +985,10 @@ PHP_FUNCTION(posix_getpwnam)
976985
PHP_FUNCTION(posix_getpwuid)
977986
{
978987
long uid;
979-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
988+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
980989
struct passwd _pw;
981990
struct passwd *retpwptr = NULL;
982-
int pwbuflen;
991+
long pwbuflen;
983992
char *pwbuf;
984993
int ret;
985994
#endif
@@ -988,8 +997,11 @@ PHP_FUNCTION(posix_getpwuid)
988997
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &uid) == FAILURE) {
989998
RETURN_FALSE;
990999
}
991-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1000+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
9921001
pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1002+
if (pwbuflen < 1) {
1003+
RETURN_FALSE;
1004+
}
9931005
pwbuf = emalloc(pwbuflen);
9941006

9951007
ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
@@ -1012,7 +1024,7 @@ PHP_FUNCTION(posix_getpwuid)
10121024
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
10131025
RETVAL_FALSE;
10141026
}
1015-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1027+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
10161028
efree(pwbuf);
10171029
#endif
10181030
}

ext/standard/filestat.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,17 @@ static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp)
363363
}
364364
convert_to_string_ex(filename);
365365
if (Z_TYPE_PP(group) == IS_STRING) {
366-
#if HAVE_GETGRNAM_R
366+
#if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
367367
struct group gr;
368368
struct group *retgrptr;
369-
int grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
370-
char *grbuf = emalloc(grbuflen);
369+
long grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
370+
char *grbuf;
371371

372+
if (grbuflen < 1) {
373+
RETURN_FALSE;
374+
}
375+
376+
grbuf = emalloc(grbuflen);
372377
if (getgrnam_r(Z_STRVAL_PP(group), &gr, grbuf, grbuflen, &retgrptr) != 0 || retgrptr == NULL) {
373378
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find gid for %s", Z_STRVAL_PP(group));
374379
efree(grbuf);
@@ -454,12 +459,17 @@ static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown)
454459
}
455460
convert_to_string_ex(filename);
456461
if (Z_TYPE_PP(user) == IS_STRING) {
457-
#if defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
462+
#if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
458463
struct passwd pw;
459464
struct passwd *retpwptr = NULL;
460-
int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
461-
char *pwbuf = emalloc(pwbuflen);
465+
long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
466+
char *pwbuf;
467+
468+
if (pwbuflen < 1) {
469+
RETURN_FALSE;
470+
}
462471

472+
pwbuf = emalloc(pwbuflen);
463473
if (getpwnam_r(Z_STRVAL_PP(user), &pw, pwbuf, pwbuflen, &retpwptr) != 0 || retpwptr == NULL) {
464474
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find uid for %s", Z_STRVAL_PP(user));
465475
efree(pwbuf);

main/fopen_wrappers.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,23 +264,37 @@ PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC)
264264
filename = SG(request_info).path_translated;
265265
path_info = SG(request_info).request_uri;
266266
#if HAVE_PWD_H
267-
if (PG(user_dir) && *PG(user_dir)
268-
&& path_info && '/' == path_info[0] && '~' == path_info[1]) {
269-
270-
char user[32];
271-
struct passwd *pw;
267+
if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) {
272268
char *s = strchr(path_info + 2, '/');
273269

274270
filename = NULL; /* discard the original filename, it must not be used */
275271
if (s) { /* if there is no path name after the file, do not bother */
276-
/* to try open the directory */
272+
char user[32]; /* to try open the directory */
273+
struct passwd *pw;
274+
#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
275+
long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
276+
char *pwbuf;
277+
278+
if (pwbuflen < 1) {
279+
return FAILURE;
280+
}
281+
282+
pwbuf = emalloc(pwbuflen);
283+
#endif
277284
length = s - (path_info + 2);
278-
if (length > (int)sizeof(user) - 1)
285+
if (length > (int)sizeof(user) - 1) {
279286
length = sizeof(user) - 1;
287+
}
280288
memcpy(user, path_info + 2, length);
281289
user[length] = '\0';
282-
290+
#if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
291+
if (getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw)) {
292+
efree(pwbuf);
293+
return FAILURE;
294+
}
295+
#else
283296
pw = getpwnam(user);
297+
#endif
284298
if (pw && pw->pw_dir) {
285299
filename = emalloc(strlen(PG(user_dir)) + strlen(path_info) + strlen(pw->pw_dir) + 4);
286300
if (filename) {

main/safe_mode.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,16 @@ PHPAPI char *php_get_current_user()
228228
return SG(request_info).current_user;
229229
#else
230230
struct passwd *pwd;
231-
#ifdef HAVE_GETPWUID_R
231+
#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
232232
struct passwd _pw;
233233
struct passwd *retpwptr = NULL;
234234
int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
235-
char *pwbuf = emalloc(pwbuflen);
235+
char *pwbuf;
236236

237+
if (pwbuflen < 1) {
238+
return ""
239+
}
240+
pwbuf = emalloc(pwbuflen);
237241
if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
238242
efree(pwbuf);
239243
return "";
@@ -246,7 +250,7 @@ PHPAPI char *php_get_current_user()
246250
#endif
247251
SG(request_info).current_user_length = strlen(pwd->pw_name);
248252
SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
249-
#ifdef HAVE_GETPWUID_R
253+
#if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
250254
efree(pwbuf);
251255
#endif
252256
return SG(request_info).current_user;

0 commit comments

Comments
 (0)