From 426dbdbfcd793758739c24f082cb0934976a63f4 Mon Sep 17 00:00:00 2001 From: Dean Sas Date: Mon, 13 Aug 2018 16:28:33 +0100 Subject: [PATCH 1/3] Ensure SFTP::rawlist gives same results regardless of statcache Previously SFTP::rawlist gave different results depending on whether the stat cache was enabled or not. With the stat cache turned off it did not treat directories correctly, as it relied on the stat cache even though it was not populated. --- phpseclib/Net/SFTP.php | 12 +++++++++- tests/Functional/Net/SFTPUserStoryTest.php | 27 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index aaff793b..c613ea8c 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -919,7 +919,17 @@ class Net_SFTP extends Net_SSH2 unset($files[$key]); continue; } - if ($key != '.' && $key != '..' && is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)))) { + $is_directory = false; + if ($key != '.' && $key != '..') { + if ($this->use_stat_cache) { + $is_directory = is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key))); + } else { + $stat = $this->stat($dir . '/' . $key); + $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY; + } + } + + if ($is_directory) { $depth++; $files[$key] = $this->rawlist($dir . '/' . $key, true); $depth--; diff --git a/tests/Functional/Net/SFTPUserStoryTest.php b/tests/Functional/Net/SFTPUserStoryTest.php index 0817345e..e39cd2f9 100644 --- a/tests/Functional/Net/SFTPUserStoryTest.php +++ b/tests/Functional/Net/SFTPUserStoryTest.php @@ -722,5 +722,32 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase $sftp->exec('ping google.com -c 5'); sleep(5); $sftp->nlist(); + + return $sftp; + } + + /** + * @depends testExecNlist + */ + public function testRawlistDisabledStatCache($sftp) + { + $this->assertTrue($sftp->chdir('unittests')); + $this->assertTrue($sftp->mkdir(self::$scratchDir)); + $this->assertTrue($sftp->chdir(self::$scratchDir)); + $this->assertTrue($sftp->put('text.txt', 'zzzzz')); + $this->assertTrue($sftp->mkdir('subdir')); + $this->assertTrue($sftp->chdir('subdir')); + $this->assertTrue($sftp->put('leaf.txt', 'yyyyy')); + $this->assertTrue($sftp->chdir('../../')); + + $list_cache_enabled = $sftp->rawlist('.', true); + + $sftp->clearStatCache(); + + $sftp->disableStatCache(); + + $list_cache_disabled = $sftp->rawlist('.', true); + + $this->assertEquals($list_cache_enabled, $list_cache_disabled, 'The files should be the same regardless of stat cache', 0.0, 10, true); } } From 6fcd8f3a6e41b31af1c69807aadea181722d5695 Mon Sep 17 00:00:00 2001 From: Dean Sas Date: Mon, 13 Aug 2018 21:44:26 +0100 Subject: [PATCH 2/3] Remove needless assertion in rawlist test --- tests/Functional/Net/SFTPUserStoryTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Functional/Net/SFTPUserStoryTest.php b/tests/Functional/Net/SFTPUserStoryTest.php index e39cd2f9..8da91604 100644 --- a/tests/Functional/Net/SFTPUserStoryTest.php +++ b/tests/Functional/Net/SFTPUserStoryTest.php @@ -731,7 +731,6 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase */ public function testRawlistDisabledStatCache($sftp) { - $this->assertTrue($sftp->chdir('unittests')); $this->assertTrue($sftp->mkdir(self::$scratchDir)); $this->assertTrue($sftp->chdir(self::$scratchDir)); $this->assertTrue($sftp->put('text.txt', 'zzzzz')); From f7f156b537748729f4fc6705563e3e85f2076b9a Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 18 Aug 2018 15:02:42 -0500 Subject: [PATCH 3/3] SFTP: use lstat in rawlist instead of stat --- phpseclib/Net/SFTP.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index c613ea8c..dc4b0df0 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -924,7 +924,7 @@ class Net_SFTP extends Net_SSH2 if ($this->use_stat_cache) { $is_directory = is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key))); } else { - $stat = $this->stat($dir . '/' . $key); + $stat = $this->lstat($dir . '/' . $key); $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY; } }