diff --git a/Archive/Tar.php b/Archive/Tar.php index 8a2d2db..a8c9501 100644 --- a/Archive/Tar.php +++ b/Archive/Tar.php @@ -2124,7 +2124,25 @@ public function _extractList( } } } elseif ($v_header['typeflag'] == "2") { - if (strpos(realpath(dirname($v_header['link'])), realpath($p_path)) !== 0) { + $link_depth = 0; + foreach (explode("/", $v_header['filename']) as $dir) { + if ($dir === "..") { + $link_depth--; + } elseif ($dir !== "" && $dir !== "." ) { + $link_depth++; + } + } + foreach (explode("/", $v_header['link']) as $dir){ + if ($link_depth <= 0) { + break; + } + if ($dir === "..") { + $link_depth--; + } elseif ($dir !== "" && $dir !== ".") { + $link_depth++; + } + } + if (strpos($v_header['link'], "/") === 0 or $link_depth <= 0) { $this->_error( 'Out-of-path file extraction {' . $v_header['filename'] . ' --> ' . diff --git a/tests/relativesymlink.phpt b/tests/relativesymlink.phpt new file mode 100644 index 0000000..68cd4b3 --- /dev/null +++ b/tests/relativesymlink.phpt @@ -0,0 +1,24 @@ +--TEST-- +test symbolic links +--SKIPIF-- +--FILE-- +extract(); +$phpunit->assertNoErrors('after'); +$phpunit->assertFileExists('testme', 'dir'); +$phpunit->assertFileExists('testme/a/file1.txt', 'file1.txt'); +$phpunit->assertFileExists('testme/b/symlink.txt', 'symlink.txt'); +$phpunit->assertTrue(is_link('testme/b/symlink.txt'), 'is link'); +echo 'tests done'; +?> +--CLEAN-- + +--EXPECT-- +tests done diff --git a/tests/relativesymlink.tar b/tests/relativesymlink.tar new file mode 100644 index 0000000..9a8867f Binary files /dev/null and b/tests/relativesymlink.tar differ