|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2017-04-01 04:07 UTC] msaladna at apisnetworks dot com
Description:
------------
Compiling PHP with ZTS affects performance of lchown and lchgrp.
PHP CLI compiled without ZTS:
./configure --disable-all
ZTS is above + '--enable-maintainer-zts'
Test script:
---------------
<?php
echo "TS: ", PHP_ZTS, "\n";
is_link("foo") && unlink("foo");
symlink("/tmp", "foo");
lchown("foo", 99);
var_dump(lstat("foo")['uid']);
?>
Expected result:
----------------
TS: 1
int(99)
Actual result:
--------------
TS: 1
int(0)
PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Dec 13 09:00:01 2025 UTC |
What is the output of the following script: <?php echo "TS: ", PHP_ZTS, "\n"; is_link("foo") && unlink("foo"); symlink("/tmp", "foo"); lchown("foo", 99); clearstatcache(true); var_dump(lstat("foo")['uid']); ?> And please check with any of the actively supported PHP versions[1]? [1] <https://www.php.net/supported-versions.php>Problem still persists. Sample code amended for clarity: <?php echo "TS: ", PHP_ZTS, " ", PHP_VERSION, "\n"; echo posix_getuid(), ":", posix_geteuid(), "\n"; is_link("foo") && unlink("foo"); symlink("/tmp", "foo"); lchown("foo", 99); clearstatcache(true); var_dump(lstat("foo")['uid']); ?> This is on a CentOS 7/PHP 7.4 machine. TS: 1 7.4.23 0:0 int(0) And on a Rocky Linux (CentOS 8)/PHP 8 machine: TS: 1 8.0.6 0:0 int(0)So this is really a bug in ZTS. The reason is that virtual_chown calls: if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) { The problem is that this calls tsrm_realpath_r which resolves the simlink in if (save && S_ISLNK(st.st_mode)) { if (++(*ll) > LINK_MAX || (j = (size_t)php_sys_readlink(tmp, path, MAXPATHLEN)) == (size_t)-1) { /* too many links or broken symlinks */ free_alloca(tmp, use_heap); return (size_t)-1; } path[j] = 0; if (IS_ABSOLUTE_PATH(path, j)) { j = tsrm_realpath_r(path, 1, j, ll, t, use_realpath, is_dir, &directory); if (j == (size_t)-1) { free_alloca(tmp, use_heap); return (size_t)-1; } } else { if (i + j >= MAXPATHLEN-1) { free_alloca(tmp, use_heap); return (size_t)-1; /* buffer overflow */ } memmove(path+i, path, j+1); memcpy(path, tmp, i-1); path[i-1] = DEFAULT_SLASH; j = tsrm_realpath_r(path, start, i + j, ll, t, use_realpath, is_dir, &directory); if (j == (size_t)-1) { free_alloca(tmp, use_heap); return (size_t)-1; } } if (link_is_dir) { *link_is_dir = directory; } } Currently it seems that it does not get resolved only for CWD_EXPAND but not 100% sure if it's safe. Anyway I created https://github.com/php/php-src/pull/20626 so it will be checked there.