@@ -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
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 , 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. */
12471262void 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
12571280static void * php_thread (void * arg ) {
0 commit comments