1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Remove include "sanity check" to get better error (#19650)

* Remove include "sanity check" to get a better error message

Instead of rejecting directories / non-regular files early with
a generic error, we should just accept them and error later when a
read is attempted. This is more general and will generate a better
error message on Linux. On Windows, the error remains the same as
before.

* Update error message to include include_path

fix format for include path

---------

Co-authored-by: Joe Watkins <krakjoe@php.net>
This commit is contained in:
Nikita Popov
2025-08-31 14:52:53 +02:00
committed by GitHub
parent 5e9080ff1b
commit ca4a841921
4 changed files with 48 additions and 26 deletions

View File

@@ -0,0 +1,21 @@
--TEST--
Including a directory generates an error
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Windows') die("skip Not for Windows");
?>
--FILE--
<?php
/* Just a random test directory */
$dir = __DIR__ . '/variadic';
require $dir;
?>
--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

View File

@@ -0,0 +1,21 @@
--TEST--
Including a directory generates an error (Windows variant)
--SKIPIF--
<?php
if (PHP_OS_FAMILY !== 'Windows') die("skip Only for Windows");
?>
--FILE--
<?php
/* Just a random test directory */
$dir = __DIR__ . '/variadic';
require $dir;
?>
--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

View File

@@ -1,5 +1,9 @@
--TEST--
Bug #35740 (memory leak when including a directory)
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Windows') die("skip Not for Windows");
?>
--FILE--
<?php
@@ -8,7 +12,7 @@ include (__DIR__);
echo "Done\n";
?>
--EXPECTF--
Warning: include(%s): Failed to open stream: %s in %s on line %d
Notice: include(): Read of %s bytes failed with errno=21 Is a directory in %s on line %d
Warning: include(): Failed opening '%s' for inclusion (include_path='%s') in %s on line %d
Done

View File

@@ -135,7 +135,6 @@ 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;
@@ -161,7 +160,7 @@ typedef struct {
static int do_fstat(php_stdio_stream_data *d, int force)
{
if (!d->cached_fstat || (force && !d->no_forced_fstat)) {
if (!d->cached_fstat || force) {
int fd;
int r;
@@ -1188,30 +1187,7 @@ 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;