@@ -121,16 +121,15 @@ private static function extract_tarball( $tarball, $dest ) {
121121 }
122122 }
123123
124- // Ensure relative paths cannot be misinterpreted as hostnames.
125- // Prepending `./` will force tar to interpret it as a filesystem path.
126- if ( self ::path_is_relative ( $ tarball ) ) {
127- $ tarball = "./ {$ tarball }" ;
124+ $ tarball_absolute = realpath ( $ tarball );
125+ if ( ! $ tarball_absolute ) {
126+ throw new Exception ( "Invalid tarball ' {$ tarball }'. " );
128127 }
128+ $ tarball = $ tarball_absolute ;
129129
130- if ( ! file_exists ( $ tarball )
131- || ! is_readable ( $ tarball )
130+ if ( ! is_readable ( $ tarball )
132131 || filesize ( $ tarball ) <= 0 ) {
133- throw new Exception ( "Invalid zip file ' {$ tarball }'. " );
132+ throw new Exception ( "Invalid tarball ' {$ tarball }'. " );
134133 }
135134
136135 // Note: directory must exist for tar --directory to work.
@@ -220,17 +219,27 @@ public static function rmdir( $dir ) {
220219 RecursiveIteratorIterator::CHILD_FIRST
221220 );
222221
222+ $ base_dir = realpath ( $ dir );
223+ if ( false === $ base_dir ) {
224+ return ;
225+ }
226+ $ base_dir = rtrim ( $ base_dir , DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR ;
227+
223228 /**
224229 * @var \SplFileInfo $fileinfo
225230 */
226231 foreach ( $ files as $ fileinfo ) {
227- $ todo = $ fileinfo ->isDir () ? 'rmdir ' : 'unlink ' ;
228- $ path = $ fileinfo ->getRealPath ();
229- if ( 0 !== strpos ( $ path , $ fileinfo ->getRealPath () ) ) {
232+ $ todo = $ fileinfo ->isDir () ? 'rmdir ' : 'unlink ' ;
233+ $ path = $ fileinfo ->getPathname ();
234+ $ real_path = $ fileinfo ->getRealPath ();
235+
236+ if ( ! $ real_path || 0 !== strpos ( $ real_path , $ base_dir ) ) {
230237 WP_CLI ::warning (
231238 "Temporary file or folder to be removed was found outside of temporary folder, aborting removal: ' {$ path }' "
232239 );
240+ continue ;
233241 }
242+
234243 $ todo ( $ path );
235244 }
236245 rmdir ( $ dir );
@@ -345,43 +354,4 @@ private static function ensure_dir_exists( $dir ) {
345354
346355 return true ;
347356 }
348-
349- /**
350- * Check whether a path is relative-
351- *
352- * @param string $path Path to check.
353- * @return bool Whether the path is relative.
354- */
355- private static function path_is_relative ( $ path ) {
356- if ( '' === $ path ) {
357- return true ;
358- }
359-
360- // Strip scheme.
361- $ scheme_position = strpos ( $ path , ':// ' );
362- if ( false !== $ scheme_position ) {
363- $ path = substr ( $ path , $ scheme_position + 3 );
364- }
365-
366- // UNIX root "/" or "\" (Windows style).
367- if ( '/ ' === $ path [0 ] || '\\' === $ path [0 ] ) {
368- return false ;
369- }
370-
371- // Windows root.
372- if ( strlen ( $ path ) > 1 && ctype_alpha ( $ path [0 ] ) && ': ' === $ path [1 ] ) {
373-
374- // Special case: only drive letter, like "C:".
375- if ( 2 === strlen ( $ path ) ) {
376- return false ;
377- }
378-
379- // Regular Windows path starting with drive letter, like "C:/ or "C:\".
380- if ( '/ ' === $ path [2 ] || '\\' === $ path [2 ] ) {
381- return false ;
382- }
383- }
384-
385- return true ;
386- }
387357}
0 commit comments