Skip to content

Commit d1b2072

Browse files
committed
keep track of separate prepared_env set for a php_server
correctly exposes env vars into $_ENV when E is in `variables_order` also fixes the problem of lazy server eval I didn't think about last commit
1 parent e81f9fb commit d1b2072

2 files changed

Lines changed: 35 additions & 5 deletions

File tree

cgi.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,17 @@ func addHeadersToServer(ctx context.Context, request *http.Request, trackVarsArr
178178
func addPreparedEnvToServer(fc *frankenPHPContext, trackVarsArray *C.zval) {
179179
for k, v := range fc.env {
180180
C.frankenphp_register_variable_safe(toUnsafeChar(k), toUnsafeChar(v), C.size_t(len(v)), trackVarsArray)
181-
// Also expose to getenv()
182-
C.frankenphp_add_to_sandboxed_env(toUnsafeChar(k), C.size_t(len(k)-1), toUnsafeChar(v), C.size_t(len(v)))
183181
}
184182
fc.env = nil
185183
}
186184

185+
// addPreparedEnvToSandbox exposes fc.env to getenv() before any PHP code runs.
186+
func addPreparedEnvToSandbox(fc *frankenPHPContext) {
187+
for k, v := range fc.env {
188+
C.frankenphp_add_to_sandboxed_env(toUnsafeChar(k), C.size_t(len(k)-1), toUnsafeChar(v), C.size_t(len(v)))
189+
}
190+
}
191+
187192
//export go_register_server_variables
188193
func go_register_server_variables(threadIndex C.uintptr_t, trackVarsArray *C.zval) {
189194
thread := phpThreads[threadIndex]
@@ -302,6 +307,8 @@ func go_update_request_info(threadIndex C.uintptr_t, info *C.sapi_request_info)
302307
return nil
303308
}
304309

310+
addPreparedEnvToSandbox(fc)
311+
305312
if m, ok := cStringHTTPMethods[request.Method]; ok {
306313
info.request_method = m
307314
} else {

frankenphp.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ HashTable *main_thread_env = NULL;
9292
__thread uintptr_t thread_index;
9393
__thread bool is_worker_thread = false;
9494
__thread HashTable *sandboxed_env = NULL;
95+
/* prepared_env holds entries from php(_server)'s `env KEY VAL`,
96+
* so they can be merged into $_ENV when 'E' is in
97+
* variables_order. Separate from putenv() so we don't leak into $_ENV*/
98+
__thread HashTable *prepared_env = NULL;
9599

96100
/* Published via SG(server_context) so ext-parallel children, which inherit
97101
* the parent's SG(server_context), can route SAPI callbacks back to the
@@ -429,9 +433,16 @@ bool frankenphp_shutdown_dummy_request(void) {
429433
}
430434

431435
void get_full_env(zval *track_vars_array) {
432-
zend_hash_extend(Z_ARR_P(track_vars_array),
433-
zend_hash_num_elements(main_thread_env), 0);
436+
size_t total = zend_hash_num_elements(main_thread_env);
437+
if (prepared_env != NULL) {
438+
// perf: doesn't matter if we get the exact count, just >= needed
439+
total += zend_hash_num_elements(prepared_env);
440+
}
441+
zend_hash_extend(Z_ARR_P(track_vars_array), total, 0);
434442
zend_hash_copy(Z_ARR_P(track_vars_array), main_thread_env, NULL);
443+
if (prepared_env != NULL) {
444+
zend_hash_copy(Z_ARR_P(track_vars_array), prepared_env, NULL);
445+
}
435446
}
436447

437448
/* Adapted from php_request_startup() */
@@ -1239,10 +1250,14 @@ static inline void reset_sandboxed_environment() {
12391250
zend_hash_release(sandboxed_env);
12401251
sandboxed_env = NULL;
12411252
}
1253+
if (prepared_env != NULL) {
1254+
zend_hash_release(prepared_env);
1255+
prepared_env = NULL;
1256+
}
12421257
}
12431258

12441259
/* Adds a key/value pair to the per-thread sandboxed environment so it becomes
1245-
* visible to getenv(). Used to expose env vars declared in the php(_server)
1260+
* visible to getenv()/$_ENV. Used to expose env vars declared in the php(_server)
12461261
* directive, which would otherwise only appear in $_SERVER. */
12471262
void frankenphp_add_to_sandboxed_env(char *name, size_t name_len, char *val,
12481263
size_t val_len) {
@@ -1252,6 +1267,14 @@ void frankenphp_add_to_sandboxed_env(char *name, size_t name_len, char *val,
12521267
zval zv = {0};
12531268
ZVAL_STRINGL(&zv, val, val_len);
12541269
zend_hash_str_update(sandboxed_env, name, name_len, &zv);
1270+
1271+
if (prepared_env == NULL) {
1272+
ALLOC_HASHTABLE(prepared_env);
1273+
zend_hash_init(prepared_env, 8, NULL, ZVAL_PTR_DTOR, 0);
1274+
}
1275+
zval zv2 = {0};
1276+
ZVAL_STRINGL(&zv2, val, val_len);
1277+
zend_hash_str_update(prepared_env, name, name_len, &zv2);
12551278
}
12561279

12571280
static void *php_thread(void *arg) {

0 commit comments

Comments
 (0)