@@ -60,6 +60,8 @@ static void test_chase_symlinks(void) {
6060 p = strjoina (temp , "/start" );
6161 assert_se (symlink ("top/dot/dotdota" , p ) >= 0 );
6262
63+ /* Paths that use symlinks underneath the "root" */
64+
6365 r = chase_symlinks (p , NULL , & result );
6466 assert_se (r >= 0 );
6567 assert_se (path_equal (result , "/usr" ));
@@ -88,6 +90,31 @@ static void test_chase_symlinks(void) {
8890 assert_se (r >= 0 );
8991 assert_se (path_equal (result , temp ));
9092
93+ /* Paths that would "escape" outside of the "root" */
94+
95+ p = strjoina (temp , "/6dots" );
96+ assert_se (symlink ("../../.." , p ) >= 0 );
97+
98+ result = mfree (result );
99+ r = chase_symlinks (p , temp , & result );
100+ assert_se (r == - EINVAL );
101+
102+ p = strjoina (temp , "/6dotsusr" );
103+ assert_se (symlink ("../../../usr" , p ) >= 0 );
104+
105+ result = mfree (result );
106+ r = chase_symlinks (p , temp , & result );
107+ assert_se (r == - EINVAL );
108+
109+ p = strjoina (temp , "/top/8dotsusr" );
110+ assert_se (symlink ("../../../../usr" , p ) >= 0 );
111+
112+ result = mfree (result );
113+ r = chase_symlinks (p , temp , & result );
114+ assert_se (r == - EINVAL );
115+
116+ /* Paths that contain repeated slashes */
117+
91118 p = strjoina (temp , "/slashslash" );
92119 assert_se (symlink ("///usr///" , p ) >= 0 );
93120
@@ -101,6 +128,8 @@ static void test_chase_symlinks(void) {
101128 assert_se (r >= 0 );
102129 assert_se (path_equal (result , q ));
103130
131+ /* Paths using . */
132+
104133 result = mfree (result );
105134 r = chase_symlinks ("/etc/./.././" , NULL , & result );
106135 assert_se (r >= 0 );
@@ -114,6 +143,8 @@ static void test_chase_symlinks(void) {
114143 r = chase_symlinks ("/etc/machine-id/foo" , NULL , & result );
115144 assert_se (r == - ENOTDIR );
116145
146+ /* Path that loops back to self */
147+
117148 result = mfree (result );
118149 p = strjoina (temp , "/recursive-symlink" );
119150 assert_se (symlink ("recursive-symlink" , p ) >= 0 );
0 commit comments