Skip to content

Commit e3c556c

Browse files
committed
MFH: Fixed FCGI_GET_VALUES requests (fixes #45522)
1 parent 55a965f commit e3c556c

File tree

4 files changed

+77
-18
lines changed

4 files changed

+77
-18
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ PHP NEWS
4848
(Christian Schneider, Arnaud)
4949
- Fixed bug #45911 (Cannot disable ext/hash). (Arnaud)
5050
- Fixed bug #45907 (undefined reference to 'PHP_SHA512Init'). (Greg)
51+
- Fixed buf #45522 (FCGI_GET_VALUES request does not return supplied values).
52+
(Arnaud)
5153
- Fixed bug #45392 (ob_start()/ob_end_clean() and memory_limit). (Ilia)
5254
- Fixed bug #45382 (timeout bug in stream_socket_enable_crypto).
5355
(vnegrier at optilian dot com, Ilia)

sapi/cgi/cgi_main.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -1608,11 +1608,18 @@ consult the installation file that came with this distribution, or visit \n\
16081608
#ifndef PHP_WIN32
16091609
/* Pre-fork, if required */
16101610
if (getenv("PHP_FCGI_CHILDREN")) {
1611-
children = atoi(getenv("PHP_FCGI_CHILDREN"));
1611+
char * children_str = getenv("PHP_FCGI_CHILDREN");
1612+
children = atoi(children_str);
16121613
if (children < 0) {
16131614
fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
16141615
return FAILURE;
16151616
}
1617+
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
1618+
/* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
1619+
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
1620+
} else {
1621+
fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
1622+
fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
16161623
}
16171624

16181625
if (children) {

sapi/cgi/fastcgi.c

+63-17
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,7 @@ typedef union _sa_t {
133133
struct sockaddr_in sa_inet;
134134
} sa_t;
135135

136-
typedef struct _fcgi_mgmt_rec {
137-
char* name;
138-
char name_len;
139-
char val;
140-
} fcgi_mgmt_rec;
141-
142-
static const fcgi_mgmt_rec fcgi_mgmt_vars[] = {
143-
{"FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, 1},
144-
{"FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, 1},
145-
{"FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, 0}
146-
};
147-
136+
static HashTable fcgi_mgmt_vars;
148137

149138
static int is_initialized = 0;
150139
static int is_fastcgi = 0;
@@ -194,6 +183,8 @@ int fcgi_in_shutdown(void)
194183
int fcgi_init(void)
195184
{
196185
if (!is_initialized) {
186+
zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
187+
fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1);
197188
#ifdef _WIN32
198189
# if 0
199190
/* TODO: Support for TCP sockets */
@@ -260,6 +251,9 @@ int fcgi_is_fastcgi(void)
260251

261252
void fcgi_shutdown(void)
262253
{
254+
if (is_initialized) {
255+
zend_hash_destroy(&fcgi_mgmt_vars);
256+
}
263257
is_fastcgi = 0;
264258
}
265259

@@ -750,8 +744,13 @@ static int fcgi_read_request(fcgi_request *req)
750744
padding = hdr.paddingLength;
751745
}
752746
} else if (hdr.type == FCGI_GET_VALUES) {
753-
int j;
754747
unsigned char *p = buf + sizeof(fcgi_header);
748+
HashPosition pos;
749+
char * str_index;
750+
uint str_length;
751+
ulong num_index;
752+
int key_type;
753+
zval ** value;
755754

756755
if (safe_read(req, buf, len+padding) != len+padding) {
757756
req->keep = 0;
@@ -763,11 +762,41 @@ static int fcgi_read_request(fcgi_request *req)
763762
return 0;
764763
}
765764

766-
for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) {
767-
if (zend_hash_exists(req->env, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].name_len+1) == 0) {
768-
sprintf((char*)p, "%c%c%s%c", fcgi_mgmt_vars[j].name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val);
769-
p += fcgi_mgmt_vars[j].name_len + 3;
765+
zend_hash_internal_pointer_reset_ex(req->env, &pos);
766+
while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
767+
int zlen;
768+
zend_hash_move_forward_ex(req->env, &pos);
769+
if (key_type != HASH_KEY_IS_STRING) {
770+
continue;
771+
}
772+
if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) {
773+
continue;
774+
}
775+
--str_length;
776+
zlen = Z_STRLEN_PP(value);
777+
if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) {
778+
break;
779+
}
780+
if (str_length < 0x80) {
781+
*p++ = str_length;
782+
} else {
783+
*p++ = ((str_length >> 24) & 0xff) | 0x80;
784+
*p++ = (str_length >> 16) & 0xff;
785+
*p++ = (str_length >> 8) & 0xff;
786+
*p++ = str_length & 0xff;
770787
}
788+
if (zlen < 0x80) {
789+
*p++ = zlen;
790+
} else {
791+
*p++ = ((zlen >> 24) & 0xff) | 0x80;
792+
*p++ = (zlen >> 16) & 0xff;
793+
*p++ = (zlen >> 8) & 0xff;
794+
*p++ = zlen & 0xff;
795+
}
796+
memcpy(p, str_index, str_length);
797+
p += str_length;
798+
memcpy(p, Z_STRVAL_PP(value), zlen);
799+
p += zlen;
771800
}
772801
len = p - buf - sizeof(fcgi_header);
773802
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
@@ -1232,6 +1261,23 @@ void fcgi_impersonate(void)
12321261
}
12331262
#endif
12341263

1264+
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len)
1265+
{
1266+
zval * zvalue;
1267+
zvalue = pemalloc(sizeof(*zvalue), 1);
1268+
Z_TYPE_P(zvalue) = IS_STRING;
1269+
Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1);
1270+
Z_STRLEN_P(zvalue) = value_len;
1271+
zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL);
1272+
}
1273+
1274+
void fcgi_free_mgmt_var_cb(void * ptr)
1275+
{
1276+
zval ** var = (zval **)ptr;
1277+
pefree(Z_STRVAL_PP(var), 1);
1278+
pefree(*var, 1);
1279+
}
1280+
12351281
/*
12361282
* Local variables:
12371283
* tab-width: 4

sapi/cgi/fastcgi.h

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ int fcgi_flush(fcgi_request *req, int close);
132132
#ifdef PHP_WIN32
133133
void fcgi_impersonate(void);
134134
#endif
135+
136+
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
137+
void fcgi_free_mgmt_var_cb(void * ptr);
138+
135139
/*
136140
* Local variables:
137141
* tab-width: 4

0 commit comments

Comments
 (0)