Bug #5888 [Opn]: System::rm doesn't properly handle symlinks
| From: | murley at townnews dot com | Date: | Mon, 07 Nov 2005 15:54:45 +0000 |
| Subject: | Bug #5888 [Opn]: System::rm doesn't properly handle symlinks | ||
| References: | 1 | Groups: | php.pear.webmaster |
| Request: | Send a blank email to pear-webmaster+get-4600@lists.php.net to get a copy of this message | ||
Edit report at http://pear.php.net/bugs/bug.php?id=5888&edit=1
ID: 5888
User updated by: murley at townnews dot com
Reported By: murley at townnews dot com
Status: Open
Id: 5888
Type: Bug
-Package: Pear
+Package: Web Site
Operating System: All unix systems
PHP Version: 4.4.1
New Comment:
Sorry, the code change should look like this:
Change to: Line 141
if (is_dir($path) && !is_link($path)) {
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);
$struct = array_merge_recursive($tmp, $struct);
} else {
Previous Comments:
------------------------------------------------------------------------
[2005-11-07 10:50:26] murley at townnews dot com
Description:
------------
The pear System::rm() method doesn't properly handle symlinks. Pear's
method for removing files and directories is there to mock the unix
style rm command. This function supports recursion as well.
When calling System::rm the internal method
_dirToStruct() is called. This method builds an array of elements,
testing each to see if it's a file or directory. The is_dir check
should be followed by an '&& !is_link' check as no unix system in the
world reads through symlinks. Doing so is *very* dangerous, and in your
case it even support filesystem jumping.
System::rm works fine on symlinks that are linked to files, but reads
through the link when a symlink goes to a directory.
Line 141 of System.php:
if (is_dir($path)) {
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);
$struct = array_merge_recursive($tmp, $struct);
} else {
On line 141 an && !is_link should be added. This will cause the
function to remove the link and not read into the directory. If left
unchanged the linked directory's content is removed but the link isn't
thus system::rm will fail.
Change to: Line 141
if (is_dir($path) && !is_link) {
$tmp = System::_dirToStruct($path, $maxinst, $aktinst+1);
$struct = array_merge_recursive($tmp, $struct);
} else {
Test script:
---------------
#!/usr/bin/php
<?php
ini_set('error_reporting', E_ALL);
require_once('System.php');
mkdir('/tmp/testrm1');
mkdir('/tmp/testrm2');
touch('/tmp/testrm2/file1');
symlink('/tmp/testrm2', '/tmp/testrm1/linkeddir2');
echo "Calling system::rm on /tmp/testrm1\n";
System::rm('-rf /tmp/testrm1');
?>
Expected result:
----------------
The expected result should be to remove the testrm1 dir and all it's
contents while leaving the testrm2 dir untouched and intact.
My sugessted changes above will fix this. Also note that once this is
changed your rm() call will mock all unix style rm's.
Actual result:
--------------
Notice that the file in testrm2 named file1 is gone and shouldnt be.
Also notice that the testrm1 dir is still there and contains and the
symlink to the directory testrm2 is still there.
------------------------------------------------------------------------
--
Edit this bug report at http://pear.php.net/bugs/bug.php?id=5888&edit=1