Skip to content

stream_is_local(): unwrap zlib and bzip2 wrappers if needed - #23714

Open
DanielEScherzer wants to merge 4 commits into
php:masterfrom
DanielEScherzer:stream_is_local
Open

DanielEScherzer wants to merge 4 commits into
php:masterfrom
DanielEScherzer:stream_is_local

Conversation

@DanielEScherzer

@DanielEScherzer DanielEScherzer commented Sep 17, 2026

Copy link
Copy Markdown
Member

When a stream is wrapped with compress.zlib://, or compress.bzip2:// , consult the appropriate stream wrapper operations to determine if a stream is local or not.

Comment thread ext/standard/streamsfuncs.c Outdated

@bukka bukka 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.

As Nora said, this is a hack. It needs to get info from the wrapper and not doing checks by name.

@DanielEScherzer

Copy link
Copy Markdown
Member Author

As Nora said, this is a hack. It needs to get info from the wrapper and not doing checks by name.

Yeah, I was trying to avoid doing large cross-cutting changes so close to the 8.6 branch, but that makes sense - done

@iliaal iliaal 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.

Two crashes reachable from the new callbacks, details inline.

Comment thread ext/zlib/zlib_fopen_wrapper.c Outdated
Comment thread ext/bz2/bz2.c Outdated
Comment thread main/streams/streams.c
Comment thread ext/zlib/zlib_fopen_wrapper.c Outdated
Comment thread ext/standard/tests/streams/stream_is_local-mixed.phpt
Add tests to demonstrate that the `zlib:`, `compress.zlib://`, and
`compress.bzip2://` wrappers also result in `stream_is_local()` returning
`true`. This behavior will be changed in a subsequent commit.
Switch `php_stream_wrapper.is_url` from a binary flag (stored as an `int`) to
an instance of the new enum `php_stream_wrapper_is_url`, which has the cases
`STREAM_IS_URL_NEVER`, `STREAM_IS_URL_ALWAYS`, and `STREAM_IS_URL_SOMETIMES`.

Add a new optional stream wrapper operation,
`php_stream_wrapper_ops.stream_is_url`, that checks if the given path should be
considered a URL or not. This callback is required when a stream wrapper is
marked as `STREAM_IS_URL_SOMETIMES`.

Update existing stream wrappers:

- most of those are marked as not being URLs (`is_url` was 0) just updated that
field to be `STREAM_IS_URL_NEVER` and added a new NULL field to their
operations.
- all of those marked as being URLs (`is_url` was 1) just updated that field to
be `STREAM_IS_URL_ALWAYS` and added a new NULL field to their operations.
- for the zlib and bz2 wrappers, which were previously marked as never being
URLs (`is_url` was 0), set the field to `STREAM_IS_URL_SOMETIMES` and implement
the new operation to strip the `compress.zlib://` and `compress.bzip2://`
prefixes respectively and then check the underlying wrapped stream.
Comment thread main/php_streams.h
struct _php_stream_wrapper {
const php_stream_wrapper_ops *wops; /* operations the wrapper can perform */
void *abstract; /* context for the wrapper */
int is_url; /* so that PG(allow_url_fopen) can be respected */
php_stream_wrapper_is_url is_url; /* so that PG(allow_url_fopen) can be respected */

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'd rather we remove this field all together and just have the wrapper ops that indicates if the stream is a URI.

Could be that if the wrapper op is NULL then assume it is an URI to be on the safe side.

This would also reduce the size from 24 to 16 due to the alignment requirements, effectively trading 8 bytes in this struct for 8 bytes in the wrapper ops struct with the new function pointer.

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 would rather change it to flags and make it more generic so we can include more info there. I had some use cases before so if we are breaking ABI, it would be better to do it in this way.

Comment thread main/php_streams.h
struct _php_stream_wrapper {
const php_stream_wrapper_ops *wops; /* operations the wrapper can perform */
void *abstract; /* context for the wrapper */
int is_url; /* so that PG(allow_url_fopen) can be respected */
php_stream_wrapper_is_url is_url; /* so that PG(allow_url_fopen) can be respected */

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 would rather change it to flags and make it more generic so we can include more info there. I had some use cases before so if we are breaking ABI, it would be better to do it in this way.

Comment thread main/php_streams.h
@@ -155,12 +155,20 @@ typedef struct _php_stream_wrapper_ops {
int (*stream_rmdir)(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context);
/* Metadata handling */
int (*stream_metadata)(php_stream_wrapper *wrapper, const char *url, int options, void *value, php_stream_context *context);
/* Required if the wrapper is_url is STREAM_IS_URL_SOMETIMES, otherwise ignored */
bool (*stream_is_url)(php_stream_wrapper *wrapper, const char *url, php_stream_context *context);

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'm not sure we should have ops just for that. Again I would prefer something more generic. I was considering to put it to metadata but it doesn't fit but need to think about other use cases as there were some IIRC

Comment thread main/php_streams.h
} php_stream_wrapper_ops;

C23_ENUM(php_stream_wrapper_is_url, uint8_t) {

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 is not a good name for enum

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.

5 participants