Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The lock is not released when putenv fails. #17403

Open
matyhtf opened this issue Jan 8, 2025 · 2 comments
Open

The lock is not released when putenv fails. #17403

matyhtf opened this issue Jan 8, 2025 · 2 comments

Comments

@matyhtf
Copy link
Contributor

matyhtf commented Jan 8, 2025

Description

https://github.com/php/php-src/blob/master/ext/standard/basic_functions.c#L846

The else branch of the putenv function does not call tsrm_env_unlock() to release the lock, which could potentially lead to a deadlock.

PHP Version

PHP 8.4

Operating System

Ubuntu 22.04

@cmb69
Copy link
Member

cmb69 commented Jan 8, 2025

Needs to be fixed for PHP-8.3+.

@matyhtf
Copy link
Contributor Author

matyhtf commented Jan 8, 2025

Hi cmb69, thanks for your reply.

Another issue is that the implementation of putenv with ZTS may have a bug. Please take a look.

The environ is a global array, if multiple threads concurrently execute putenv with the same key, the pe.previous_value pointer may point to a memory address that has already been freed.

The putenv C function does not copy the string that is passed in; instead, it directly stores the pointer in environ.

Thread 1:

RINIT
putenv(env1)
pe.previous_value = NULL
// ... more code 

Thread 2:

env1 and env2 have the same key

RINIT
putenv(env2)
pe.previous_value = env1

Thread 1:

RSHUTDOWN
// php_putenv_destructor()
free(pe->putenv_string) // free env1

Thread 2:

RSHUTDOWN
// php_putenv_destructor()
// pe->previous_value is env1
putenv(pe->previous_value) // This memory address has already been freed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants