Skip to content

SAPI: Convert sapi_getenv to zend_string - #23386

Open
NattyNarwhal wants to merge 1 commit into
php:masterfrom
NattyNarwhal:sapi-getenv-zend-string
Open

SAPI: Convert sapi_getenv to zend_string#23386
NattyNarwhal wants to merge 1 commit into
php:masterfrom
NattyNarwhal:sapi-getenv-zend-string

Conversation

@NattyNarwhal

Copy link
Copy Markdown
Member

The old char* return was very ambigious at the SAPI level about ownership per platform (unix returned environ buffer, Win32 returned converted buffer), which it then estrduped at the SAPI frontend level. To clarify this, instead return an allocated zend_string in the SAPIs which we bubble up to consumers.

There are some annoyances still; input filters have to shuffle some buffers because input filters expect to work on raw buffers, and phar does some mildly harrowing string mangling without zend_string. These should be cleaned up.

There is also the question if SAPIs just bubbling up getenv when they lack a web server specific context i.e. from fcgi or Apache (CGI, FPM, Litespeed), as this seems not quite the right intent; CLI doesn't implement a getenv function for instance.

@LamentXU123 LamentXU123 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phar part. I am in favor of this.

Comment thread ext/phar/phar_object.c Outdated
entry = path_info;
if (zs_path_info) {
entry = estrdup(ZSTR_VAL(zs_path_info));
entry_len = strlen(entry);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can just be

Suggested change
entry_len = strlen(entry);
entry_len = ZSTR_LEN(zs_path_info);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

estrdup will cut off after the first NUL byte, so if there's an embedded NUL byte then entry_len will go out of bounds. Can't happen with environment variables on their wn, but perhaps via input filters it can

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:| welp I hope that input filter can't mess up like that but this is PHP we're talking about. Might make sense to guard strings that have nul bytes in them as that seems potentially problematic.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I do have a draft branch (not committed/pushed yet) for trying to make input filters use zend_string as well (since it's ugly in sapi_getenv and also the API of the filters are as well), but it's a mild slog that touches a surprising amount of stuff.

For the phar path mangling here, this should also just be zend_stringified the whole way through. Doable, just annoying

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was working on converting char* to zend_string in phar and there might even still be a PR somewhere that does this (or somewhere on my local machine) but those conversions can be quite tedious yeah.

@LamentXU123 LamentXU123 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I am a bit awake now. I don't know much about sapi but I have some comments.
Also, I think the fpm logic is weird. But since I don't know how it works internally (and I don't want to read the code base anymore...) I don't review that part.

Comment thread ext/phar/phar_object.c Outdated
Comment thread sapi/litespeed/lsapi_main.c Outdated
Comment thread sapi/cgi/cgi_main.c
ret = getenv(name);
}
return ret ? zend_string_init(ret, strlen(ret), 0) : NULL;
#else

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the logic. But seems like you've missed something here? if ret is not empty we should use ret, this is also true in the else branch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot the logic in the Windows ifdef, that should be fixed.

Comment thread sapi/fpm/fpm/fpm_main.c Outdated
Comment thread sapi/fpm/fpm/fpm_main.c
The old char* return was very ambigious at the SAPI level about
ownership per platform (unix returned environ buffer, Win32 returned
converted buffer), which it then estrduped at the SAPI frontend level.
To clarify this, instead return an allocated zend_string in the SAPIs
which we bubble up to consumers.

There are some annoyances still; input filters have to shuffle some
buffers because input filters expect to work on raw buffers, and phar
does some mildly harrowing string mangling without zend_string. These
should be cleaned up.

There is also the question if SAPIs just bubbling up getenv when they
lack a web server specific context i.e. from fcgi or Apache  (CGI, FPM,
Litespeed), as this seems not quite the right intent; CLI doesn't
implement a getenv function for instance.
@NattyNarwhal
NattyNarwhal force-pushed the sapi-getenv-zend-string branch from 94c08df to fc20723 Compare August 21, 2026 03:13
@NattyNarwhal

Copy link
Copy Markdown
Member Author

Addressed your comments.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants