From 22341e662ba889edc0c1b666c43a570ee95a9d14 Mon Sep 17 00:00:00 2001 From: Sjoerd Langkemper Date: Sun, 18 Oct 2026 10:08:41 +0000 Subject: [PATCH] ext/iconv, ext/standard: make tests more robust on FreeBSD I ran PHP's tests on FreeBSD 15.1, and these were failing: - ext/iconv/tests/bug52211.phpt: trigger the error with an incomplete UTF-8 source sequence. Rejecting a valid but unrepresentable character is implementation-defined; FreeBSD's ASCII passes bytes through for identity conversions, while glibc rejects them. https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=296765 - ext/standard/tests/file/chmod_basic.phpt: probe which special mode bits can be set on a regular file. FreeBSD rejects the sticky bit on regular files with EFTYPE. - ext/standard/tests/file/006_variation2.phpt: apply the sticky bit only to the directory, whose semantics are portable, and update the expected file modes. - ext/standard/tests/ini_info/php_ini_loaded_file.phpt: do not forward TEST_PHP_EXTRA_ARGS for the "no ini file" case. It can contain -c, which takes precedence over -n, causing the child to load run-tests.php's temporary ini file. Also clear the stat cache before calling fileperms(), not after. --- ext/iconv/tests/bug52211.phpt | 23 +++++---------- ext/standard/tests/file/006_variation2.phpt | 28 +++++++++++-------- ext/standard/tests/file/chmod_basic.phpt | 24 +++++++++++++--- .../tests/ini_info/php_ini_loaded_file.phpt | 6 ++-- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/ext/iconv/tests/bug52211.phpt b/ext/iconv/tests/bug52211.phpt index fe599f8ac559..4ab2c6a67b74 100644 --- a/ext/iconv/tests/bug52211.phpt +++ b/ext/iconv/tests/bug52211.phpt @@ -5,22 +5,13 @@ iconv --FILE-- diff --git a/ext/standard/tests/file/006_variation2.phpt b/ext/standard/tests/file/006_variation2.phpt index 6b32f2246f12..2bf7db5e7b78 100644 --- a/ext/standard/tests/file/006_variation2.phpt +++ b/ext/standard/tests/file/006_variation2.phpt @@ -49,20 +49,26 @@ $perms_array = array( $count = 1; foreach($perms_array as $permission) { echo "-- Iteration $count --\n"; + + // The sticky bit has platform-specific semantics on regular files and + // is rejected by some systems (e.g. FreeBSD) with EFTYPE. It is still + // tested on the directory below. + $file_permission = is_int($permission) ? $permission & 07777 & ~01000 : $permission; + try { - var_dump( chmod($file_name, $permission) ); + var_dump( chmod($file_name, $file_permission) ); + clearstatcache(); printf("%o", fileperms($file_name) ); echo "\n"; - clearstatcache(); } catch (TypeError $e) { echo $e->getMessage(), "\n"; } try { var_dump( chmod($dir_name, $permission) ); + clearstatcache(); printf("%o", fileperms($dir_name) ); echo "\n"; - clearstatcache(); } catch (TypeError $e) { echo $e->getMessage(), "\n"; } @@ -83,7 +89,7 @@ rmdir(__DIR__."/006_variation2"); *** Testing fileperms(), chmod() with miscellaneous permissions *** -- Iteration 1 -- bool(true) -107777 +106777 bool(true) 47777 -- Iteration 2 -- @@ -93,17 +99,17 @@ bool(true) 40000 -- Iteration 3 -- bool(true) -101000 +100000 bool(true) 41000 -- Iteration 4 -- bool(true) -101111 +100111 bool(true) 41111 -- Iteration 5 -- bool(true) -107001 +106001 bool(true) 47001 -- Iteration 6 -- @@ -113,12 +119,12 @@ bool(true) 40001 -- Iteration 7 -- bool(true) -101411 +100411 bool(true) 41411 -- Iteration 8 -- bool(true) -107141 +106141 bool(true) 47141 -- Iteration 9 -- @@ -128,12 +134,12 @@ bool(true) 40637 -- Iteration 10 -- bool(true) -103567 +102567 bool(true) 43567 -- Iteration 11 -- bool(true) -103567 +102567 bool(true) 43567 -- Iteration 12 -- diff --git a/ext/standard/tests/file/chmod_basic.phpt b/ext/standard/tests/file/chmod_basic.phpt index 635ea8de7981..dd1ebe51ce9e 100644 --- a/ext/standard/tests/file/chmod_basic.phpt +++ b/ext/standard/tests/file/chmod_basic.phpt @@ -16,12 +16,28 @@ $filename = __FILE__ . ".tmp"; $fd = fopen($filename, "w+"); fclose($fd); +// Not all platforms allow every mode bit on a regular file. FreeBSD, for +// example, rejects the sticky bit with EFTYPE. Detect the supported bits +// first, so that the test does not depend on platform-specific semantics. +$mode_mask = 0777; +foreach ([04000, 02000, 01000] as $bit) { + @chmod($filename, 0777); + clearstatcache(); + if (@chmod($filename, 0777 | $bit)) { + clearstatcache(); + if (fileperms($filename) & $bit) { + $mode_mask |= $bit; + } + } +} + for ($perms_to_set = 07777; $perms_to_set >= 0; $perms_to_set--) { - chmod($filename, $perms_to_set); - $set_perms = (fileperms($filename) & MODE_MASK); + $perms = $perms_to_set & $mode_mask; + chmod($filename, $perms); clearstatcache(); - if ($set_perms != $perms_to_set) { - printf("Error: %o does not match %o\n", $set_perms, $perms_to_set); + $set_perms = (fileperms($filename) & MODE_MASK); + if ($set_perms != $perms) { + printf("Error: %o does not match %o\n", $set_perms, $perms); } } var_dump(chmod($filename, 0777)); diff --git a/ext/standard/tests/ini_info/php_ini_loaded_file.phpt b/ext/standard/tests/ini_info/php_ini_loaded_file.phpt index 4e3085ba8653..15d4b2fb8441 100644 --- a/ext/standard/tests/ini_info/php_ini_loaded_file.phpt +++ b/ext/standard/tests/ini_info/php_ini_loaded_file.phpt @@ -7,8 +7,10 @@ php_ini_loaded_file() function $args = getenv('TEST_PHP_EXTRA_ARGS'); $code = '"var_dump(php_ini_loaded_file());"'; - // No ini file - passthru("$php $args -n -r $code"); + // No ini file. Do not pass TEST_PHP_EXTRA_ARGS here: it can contain a + // -c option (e.g. when run-tests.php is invoked with -c, as "make test" + // does) which takes precedence over -n. + passthru("$php -n -r $code"); // Specified ini file passthru("$php $args -c $inifile -r $code");