@@ -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,17 @@ bool frankenphp_shutdown_dummy_request(void) {
429433}
430434
431435void 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 ,
445+ (copy_ctor_func_t )zval_add_ref );
446+ }
435447}
436448
437449/* Adapted from php_request_startup() */
@@ -1239,6 +1251,30 @@ static inline void reset_sandboxed_environment() {
12391251 zend_hash_release (sandboxed_env );
12401252 sandboxed_env = NULL ;
12411253 }
1254+ if (prepared_env != NULL ) {
1255+ zend_hash_release (prepared_env );
1256+ prepared_env = NULL ;
1257+ }
1258+ }
1259+
1260+ /* Adds a key/value pair to the per-thread sandboxed environment so it becomes
1261+ * visible to getenv()/$_ENV. Used to expose env vars declared in the
1262+ * php(_server) directive, which would otherwise only appear in $_SERVER. */
1263+ void frankenphp_add_to_sandboxed_env (char * name , size_t name_len , char * val ,
1264+ size_t val_len ) {
1265+ if (sandboxed_env == NULL ) {
1266+ sandboxed_env = zend_array_dup (main_thread_env );
1267+ }
1268+ zval zv = {0 };
1269+ ZVAL_STRINGL (& zv , val , val_len );
1270+ zend_hash_str_update (sandboxed_env , name , name_len , & zv );
1271+
1272+ if (prepared_env == NULL ) {
1273+ prepared_env = zend_new_array (8 );
1274+ }
1275+ zval zv2 = {0 };
1276+ ZVAL_STRINGL (& zv2 , val , val_len );
1277+ zend_hash_str_update (prepared_env , name , name_len , & zv2 );
12421278}
12431279
12441280static void * php_thread (void * arg ) {
0 commit comments