Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ PHP NEWS
parsing fails after Transfer-Encoding). (bercedev)
. Fixed bug GH-24509 (HTTP wrapper leaks Location buffer on empty
Location header). (bercedev)
. Fixed bug GH-24707 (Use-after-free in opendir() when a user wrapper
unregisters itself). (lazerg)

- Zip:
. Reject broken libzip versions 1.3.1, 1.7.0 and 1.12.0 during Windows
Expand Down
18 changes: 18 additions & 0 deletions ext/standard/tests/streams/gh24707.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
GH-24707 (Use-after-free in opendir() when a user wrapper unregisters itself)
--FILE--
<?php
class Wrapper {
public $context;

public function dir_opendir(string $path, int $options): bool {
stream_wrapper_unregister('foo');
return false;
}
}
stream_wrapper_register('foo', 'Wrapper');
var_dump(opendir('foo://'));
?>
--EXPECTF--
Warning: opendir(): Failed to open directory: "Wrapper::dir_opendir" call failed in %s on line %d
bool(false)
7 changes: 5 additions & 2 deletions main/streams/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -2104,6 +2104,8 @@ PHPAPI php_stream *_php_stream_opendir(const char *path, int options,
return NULL;
}

/* wrapper name needs to be stored as wrapper can be removed in opener (user stream) */
char *wrapper_name = estrdup(PHP_STREAM_ERROR_WRAPPER_NAME(wrapper));
stream = wrapper->wops->dir_opener(wrapper,
path_to_open, "r", options & ~REPORT_ERRORS, NULL,
context STREAMS_REL_CC);
Expand All @@ -2112,10 +2114,11 @@ PHPAPI php_stream *_php_stream_opendir(const char *path, int options,
stream->wrapper = wrapper;
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER | PHP_STREAM_FLAG_IS_DIR;
} else if (options & REPORT_ERRORS) {
php_stream_display_wrapper_errors(wrapper, context, PHP_STREAM_EC(OpenFailed),
php_stream_display_wrapper_name_errors(wrapper_name, context, PHP_STREAM_EC(OpenFailed),
"Failed to open directory");
}
php_stream_tidy_wrapper_error_log(wrapper);
php_stream_tidy_wrapper_name_error_log(wrapper_name);
efree(wrapper_name);

return stream;
}
Expand Down
Loading