Merge branch 'PHP-8.3' into PHP-8.4

This commit is contained in:
Jakub Zelenka 2025-02-24 23:22:47 +01:00
commit ed00c1d74b
No known key found for this signature in database
GPG key ID: 1C0779DC5C0A9DE4
7 changed files with 158 additions and 4 deletions

4
NEWS
View file

@ -81,6 +81,10 @@ PHP NEWS
. Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c). . Fixed bug GH-15902 (Core dumped in ext/reflection/php_reflection.c).
(DanielEScherzer) (DanielEScherzer)
- Standard:
. Fixed bug #72666 (stat cache clearing inconsistent between file:// paths
and plain paths). (Jakub Zelenka)
- Streams: - Streams:
. Fixed bug GH-17650 (realloc with size 0 in user_filters.c). (nielsdos) . Fixed bug GH-17650 (realloc with size 0 in user_filters.c). (nielsdos)
. Fix memory leak on overflow in _php_stream_scandir(). (nielsdos) . Fix memory leak on overflow in _php_stream_scandir(). (nielsdos)

View file

@ -388,6 +388,9 @@ static void php_do_chgrp(INTERNAL_FUNCTION_PARAMETERS, int do_lchgrp) /* {{{ */
php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
php_clear_stat_cache(0, NULL, 0);
RETURN_TRUE; RETURN_TRUE;
#endif #endif
} }
@ -527,6 +530,9 @@ static void php_do_chown(INTERNAL_FUNCTION_PARAMETERS, int do_lchown) /* {{{ */
php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
php_clear_stat_cache(0, NULL, 0);
RETURN_TRUE; RETURN_TRUE;
#endif #endif
} }
@ -591,6 +597,9 @@ PHP_FUNCTION(chmod)
php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
php_clear_stat_cache(0, NULL, 0);
RETURN_TRUE; RETURN_TRUE;
} }
/* }}} */ /* }}} */
@ -676,6 +685,9 @@ PHP_FUNCTION(touch)
php_error_docref(NULL, E_WARNING, "Utime failed: %s", strerror(errno)); php_error_docref(NULL, E_WARNING, "Utime failed: %s", strerror(errno));
RETURN_FALSE; RETURN_FALSE;
} }
php_clear_stat_cache(0, NULL, 0);
RETURN_TRUE; RETURN_TRUE;
} }
/* }}} */ /* }}} */

View file

@ -0,0 +1,19 @@
--TEST--
Bug #72666 (stat cache clearing inconsistent - touch)
--FILE--
<?php
$filename = __DIR__ . '/bug72666_variation1.txt';
touch($filename);
var_dump(filemtime($filename) > 2);
touch($filename, 1);
var_dump(filemtime($filename));
?>
--CLEAN--
<?php
unlink(__DIR__ . '/bug72666_variation1.txt');
?>
--EXPECT--
bool(true)
int(1)

View file

@ -0,0 +1,35 @@
--TEST--
Bug #72666 (stat cache clearing inconsistent - chgrp, chmod)
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip no windows support');
if (!function_exists("posix_getgid")) die("skip no posix_getgid()");
?>
--FILE--
<?php
$filename = __DIR__ . '/bug72666_variation2.txt';
$gid = posix_getgid();
var_dump(touch($filename));
$ctime1 = filectime($filename);
sleep(1);
var_dump(chgrp($filename,$gid));
$ctime2 = filectime($filename);
sleep(1);
var_dump(chmod($filename, 0777));
$ctime3 = filectime($filename);
var_dump($ctime2 > $ctime1);
var_dump($ctime3 > $ctime2);
?>
--CLEAN--
<?php
unlink(__DIR__ . '/bug72666_variation2.txt');
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)

View file

@ -0,0 +1,35 @@
--TEST--
Bug #72666 (stat cache clearing inconsistent - plain wrapper)
--FILE--
<?php
$filename = __DIR__ . '/bug72666_variation3.txt';
file_put_contents($filename, "test");
$fd = fopen($filename, "r");
$atime1 = fileatime($filename);
sleep(1);
var_dump(fread($fd, 4));
$atime2 = fileatime($filename);
$mtime1 = filemtime($filename);
fclose($fd);
$fd = fopen($filename, "w");
sleep(1);
var_dump(fwrite($fd, "data"));
$mtime2 = filemtime($filename);
if (substr(PHP_OS, 0, 3) == 'WIN') {
// Windows do not hundle atime
var_dump($atime2 == $atime1);
} else {
var_dump($atime2 > $atime1);
}
var_dump($mtime2 > $mtime1);
?>
--CLEAN--
<?php
unlink(__DIR__ . '/bug72666_variation3.txt');
?>
--EXPECT--
string(4) "test"
int(4)
bool(true)
bool(true)

View file

@ -0,0 +1,26 @@
--TEST--
Bug #72666 (stat cache clearing inconsistent - exec)
--FILE--
<?php
$filename = __DIR__ . '/bug72666_variation4.txt';
touch($filename, 1);
var_dump(filemtime($filename));
exec("touch $filename");
var_dump(filemtime($filename) > 1);
touch($filename, 1);
var_dump(filemtime($filename));
shell_exec("touch $filename");
var_dump(filemtime($filename) > 1);
?>
--CLEAN--
<?php
unlink(__DIR__ . '/bug72666_variation4.txt');
?>
--EXPECT--
int(1)
bool(true)
int(1)
bool(true)

View file

@ -349,14 +349,15 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t count) static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t count)
{ {
php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
ssize_t bytes_written;
assert(data != NULL); assert(data != NULL);
if (data->fd >= 0) { if (data->fd >= 0) {
#ifdef PHP_WIN32 #ifdef PHP_WIN32
ssize_t bytes_written = _write(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); bytes_written = _write(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count));
#else #else
ssize_t bytes_written = write(data->fd, buf, count); bytes_written = write(data->fd, buf, count);
#endif #endif
if (bytes_written < 0) { if (bytes_written < 0) {
if (PHP_IS_TRANSIENT_ERROR(errno)) { if (PHP_IS_TRANSIENT_ERROR(errno)) {
@ -370,7 +371,6 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno)); php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno));
} }
} }
return bytes_written;
} else { } else {
#ifdef HAVE_FLUSHIO #ifdef HAVE_FLUSHIO
@ -380,8 +380,15 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
data->last_op = 'w'; data->last_op = 'w';
#endif #endif
return (ssize_t) fwrite(buf, 1, count, data->file); bytes_written = (ssize_t) fwrite(buf, 1, count, data->file);
} }
if (EG(active)) {
/* clear stat cache as mtime and ctime got changed */
php_clear_stat_cache(0, NULL, 0);
}
return bytes_written;
} }
static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count) static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
@ -460,6 +467,12 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
stream->eof = feof(data->file); stream->eof = feof(data->file);
} }
if (EG(active)) {
/* clear stat cache as atime got changed */
php_clear_stat_cache(0, NULL, 0);
}
return ret; return ret;
} }
@ -540,6 +553,10 @@ static int php_stdiop_flush(php_stream *stream)
* something completely different. * something completely different.
*/ */
if (data->file) { if (data->file) {
if (EG(active)) {
/* clear stat cache as there might be a write so mtime and ctime might have changed */
php_clear_stat_cache(0, NULL, 0);
}
return fflush(data->file); return fflush(data->file);
} }
return 0; return 0;
@ -1154,6 +1171,12 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zen
ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id, (open_flags & O_APPEND) == 0); ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id, (open_flags & O_APPEND) == 0);
} }
if (EG(active)) {
/* clear stat cache as mtime and ctime might got changed - phar can use stream before
* cache is initialized so we need to check if the execution is active. */
php_clear_stat_cache(0, NULL, 0);
}
if (ret) { if (ret) {
if (opened_path) { if (opened_path) {
*opened_path = zend_string_init(realpath, strlen(realpath), 0); *opened_path = zend_string_init(realpath, strlen(realpath), 0);