diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 0bdfc5d37f01a..66f7fea5a724e 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -14,7 +14,6 @@ PHP 8.5 INTERNALS UPGRADE NOTES 1. Internal API changes ======================== -- Core . PG(arg_separator).input and PG(arg_separator).output are now `zend_string*` instead of `char*`. . DL_LOAD now doesn't use RTLD_DEEPBIND deepbind anymore on platforms @@ -34,16 +33,6 @@ PHP 8.5 INTERNALS UPGRADE NOTES pointer. If the error will be delayed until runtime, it is stored in the new `validation_error` field of the `zend_attribute` struct. RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute - -- Hash - . Hash functions now use proper hash_spec_result enum for return values - instead of using SUCCESS and FAILURE. - -- Random - . The handlers parameter of php_random_engine_common_init() has been - removed. Use the default_object_handlers field on the CE instead. - -- Zend . Added zend_safe_assign_to_variable_noref() function to safely assign a value to a non-reference zval. . Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor @@ -91,13 +80,6 @@ PHP 8.5 INTERNALS UPGRADE NOTES from the parent process after a fork(). . HASH_KEY_IS_* constants have been moved in the zend_hash_key_type enum. -- standard - . ext/standard/php_smart_string.h and ext/standard/php_smart_string_public.h - were removed. Use the corresponding headers in Zend/ instead. - -- URI - . Internal API for URI handling was added via the php_uri_*() functions. - ======================== 2. Build system changes ======================== @@ -136,26 +118,34 @@ PHP 8.5 INTERNALS UPGRADE NOTES 3. Module changes ======================== -- ext/gd +- Gd: . The gdImageScale*() and gdImageRotate*() helpers are now internal in the bundled libgd, like they have been in external libgd as of gd-2.1.1. -- ext/json +- Hash: + . Hash functions now use proper hash_spec_result enum for return values + instead of using SUCCESS and FAILURE. + +- JSON: . php_json_encode_serializable_object() now assumes `EG(active)`, if not a bailout is caused. Therefore a minor BC break exists if the `PHP_JSON_PARTIAL_OUTPUT_ON_ERROR` option is in use. However, this situation is highly unlikely. -- ext/libxml +- Libxml: . The refcount APIs now return an `unsigned int` instead of an `int`. . Removed php_libxml_xmlCheckUTF8(). Use xmlCheckUTF8() from libxml instead. -- ext/pdo +- PDO: . Added `php_pdo_stmt_valid_db_obj_handle()` to check if the database object is still valid. This is useful when a GC cycle is collected and the database object can be destroyed prior to destroying the statement. -- ext/standard +- Random: + . The handlers parameter of php_random_engine_common_init() has been + removed. Use the default_object_handlers field on the CE instead. + +- Standard: . Added php_url_decode_ex() and php_raw_url_decode_ex() that unlike their non-ex counterparts do not work in-place. . The php_std_date() function has been removed. Use php_format_date() with @@ -165,6 +155,11 @@ PHP 8.5 INTERNALS UPGRADE NOTES and image_type_to_extension() is now extensible using the internal APIs php_image_register_handler() and php_image_unregister_handler() in php_image.h. + . ext/standard/php_smart_string.h and ext/standard/php_smart_string_public.h + were removed. Use the corresponding headers in Zend/ instead. + +- URI: + . Internal API for URI handling was added via the php_uri_*() functions. ======================== 4. OpCode changes diff --git a/Zend/tests/require_directory.phpt b/Zend/tests/require_directory.phpt deleted file mode 100644 index c8b4b6a6382cb..0000000000000 --- a/Zend/tests/require_directory.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Including a directory generates an error ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -Notice: require(): Read of %d bytes failed with errno=21 Is a directory in %s on line %d - -Fatal error: Uncaught Error: Failed opening required '%s' (include_path='.:') in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/Zend/tests/require_directory_windows.phpt b/Zend/tests/require_directory_windows.phpt deleted file mode 100644 index d8b68c2064e57..0000000000000 --- a/Zend/tests/require_directory_windows.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Including a directory generates an error (Windows variant) ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -Warning: require(%s): Failed to open stream: Permission denied in %s on line %d - -Fatal error: Uncaught Error: Failed opening required '%s' (include_path='%s') in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/ext/standard/tests/file/bug35740.phpt b/ext/standard/tests/file/bug35740.phpt index d06b53be06ed8..29ab0248d8dcf 100644 --- a/ext/standard/tests/file/bug35740.phpt +++ b/ext/standard/tests/file/bug35740.phpt @@ -1,9 +1,5 @@ --TEST-- Bug #35740 (memory leak when including a directory) ---SKIPIF-- - --FILE-- --EXPECTF-- -Notice: include(): Read of %s bytes failed with errno=21 Is a directory in %s on line %d +Warning: include(%s): Failed to open stream: %s in %s on line %d Warning: include(): Failed opening '%s' for inclusion (include_path='%s') in %s on line %d Done diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index a0471a8b9218c..a8fd70b8d6ac2 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -135,6 +135,7 @@ typedef struct { unsigned is_pipe:1; /* stream is an actual pipe, currently Windows only*/ unsigned cached_fstat:1; /* sb is valid */ unsigned is_pipe_blocking:1; /* allow blocking read() on pipes, currently Windows only */ + unsigned no_forced_fstat:1; /* Use fstat cache even if forced */ unsigned is_seekable:1; /* don't try and seek, if not set */ unsigned _reserved:26; @@ -160,7 +161,7 @@ typedef struct { static int do_fstat(php_stdio_stream_data *d, int force) { - if (!d->cached_fstat || force) { + if (!d->cached_fstat || (force && !d->no_forced_fstat)) { int fd; int r; @@ -1187,7 +1188,30 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zen efree(persistent_id); } + /* WIN32 always set ISREG flag */ #ifndef PHP_WIN32 + /* sanity checks for include/require. + * We check these after opening the stream, so that we save + * on fstat() syscalls */ + if (options & STREAM_OPEN_FOR_INCLUDE) { + php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; + int r; + + r = do_fstat(self, 0); + if ((r == 0 && !S_ISREG(self->sb.st_mode))) { + if (opened_path) { + zend_string_release_ex(*opened_path, 0); + *opened_path = NULL; + } + php_stream_close(ret); + return NULL; + } + + /* Make sure the fstat result is reused when we later try to get the + * file size. */ + self->no_forced_fstat = 1; + } + if (options & STREAM_USE_BLOCKING_PIPE) { php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; self->is_pipe_blocking = 1;