From 8226356b7bd3874bc1bba55d9ec8e32d1de8ebe1 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 9 Nov 2021 18:31:05 -0800 Subject: [PATCH] CRM_Utils_File::isChildPath - Fix checking of non-existent paths Suppose you use call `isChildPath()` with these options: * `$parent='/nonexistent'` * `$child='/home/me/exists.txt'` * `$checkRealPath=TRUE` Before ===== Reports that `/home/me/exists.txt` is a child of `/nonexistent` After ===== Reports that `/home/me/exists.txt` is NOT a child of `/nonexistent` Comments ======== I added six test cases for how `isChildPath()` behaves when using `$checkRealPath=TRUE`. The first five cases behave the same with or without the patch. The patch fixes the last case. --- CRM/Utils/File.php | 3 +++ tests/phpunit/CRM/Utils/FileTest.php | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CRM/Utils/File.php b/CRM/Utils/File.php index 4fd3706bfa..e4df98f11f 100644 --- a/CRM/Utils/File.php +++ b/CRM/Utils/File.php @@ -802,6 +802,9 @@ HTACCESS; if ($checkRealPath) { $parent = realpath($parent); $child = realpath($child); + if ($parent === FALSE || $child === FALSE) { + return FALSE; + } } $parentParts = explode('/', rtrim($parent, '/')); $childParts = explode('/', rtrim($child, '/')); diff --git a/tests/phpunit/CRM/Utils/FileTest.php b/tests/phpunit/CRM/Utils/FileTest.php index 94e2618228..f475f92746 100644 --- a/tests/phpunit/CRM/Utils/FileTest.php +++ b/tests/phpunit/CRM/Utils/FileTest.php @@ -18,7 +18,22 @@ class CRM_Utils_FileTest extends CiviUnitTestCase { $testCases[] = ['/ab/cd', 'ab/cd/ef', FALSE]; foreach ($testCases as $testCase) { $actual = CRM_Utils_File::isChildPath($testCase[0], $testCase[1], FALSE); - $this->assertEquals($testCase[2], $actual, sprintf("parent=[%s] child=[%s] expected=[%s] actual=[%s]", + $this->assertEquals($testCase[2], $actual, sprintf("parent=[%s] child=[%s] checkRealPath=[FALSE] expected=[%s] actual=[%s]", + $testCase[0], $testCase[1], $testCase[2], $actual + )); + } + + global $civicrm_root; + $realCases = []; + $realCases[] = ["$civicrm_root", "$civicrm_root/CRM", TRUE]; + $realCases[] = ["$civicrm_root/CRM", "$civicrm_root", FALSE]; + $realCases[] = ["/nonexistent", "/nonexistent/child", FALSE]; + $realCases[] = ["/nonexistent/child", "/nonexistent", FALSE]; + $realCases[] = ["$civicrm_root", "/nonexistent", FALSE]; + $realCases[] = ["/nonexistent", "$civicrm_root", FALSE]; + foreach ($realCases as $testCase) { + $actual = CRM_Utils_File::isChildPath($testCase[0], $testCase[1], TRUE); + $this->assertEquals($testCase[2], $actual, sprintf("parent=[%s] child=[%s] checkRealPath=[TRUE] expected=[%s] actual=[%s]", $testCase[0], $testCase[1], $testCase[2], $actual )); } -- 2.25.1