Make WordPress Core

Changeset 59257


Ignore:
Timestamp:
10/18/2024 11:35:02 PM (2 years ago)
Author:
azaozz
Message:

Upgrade/Install: Return WP_Error when source files cannot be found.

Fixes a fatal error in array_keys() (PHP 8.0+) as $wp_filesystem->dirlist() will return false when the source directory doesn't exist or becomes unreadable for some reason.

Props: verygoode, lifelightweb, da5f656f, costdev, afragen, azaozz
Fixes #61114

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-upgrader.php

    r59039 r59257  
    205205                $this->strings['incompatible_archive'] = __( 'The package could not be installed.' );
    206206                $this->strings['files_not_writable']   = __( 'The update cannot be installed because some files could not be copied. This is usually due to inconsistent file permissions.' );
     207                $this->strings['dir_not_readable']     = __( 'A directory could not be read.' );
    207208
    208209                $this->strings['maintenance_start'] = __( 'Enabling Maintenance mode…' );
     
    559560                $local_destination = $destination;
    560561
    561                 $source_files       = array_keys( $wp_filesystem->dirlist( $remote_source ) );
     562                $dirlist = $wp_filesystem->dirlist( $remote_source );
     563
     564                if ( false === $dirlist ) {
     565                        return new WP_Error( 'source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
     566                }
     567
     568                $source_files       = array_keys( $dirlist );
    562569                $remote_destination = $wp_filesystem->find_folder( $local_destination );
    563570
     
    606613                // Has the source location changed? If so, we need a new source_files list.
    607614                if ( $source !== $remote_source ) {
    608                         $source_files = array_keys( $wp_filesystem->dirlist( $source ) );
     615                        $dirlist = $wp_filesystem->dirlist( $source );
     616
     617                        if ( false === $dirlist ) {
     618                                return new WP_Error( 'new_source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
     619                        }
     620
     621                        $source_files = array_keys( $dirlist );
    609622                }
    610623
  • trunk/tests/phpunit/tests/admin/wpUpgrader.php

    r58022 r59257  
    950950
    951951        /**
     952         * Tests that `WP_Upgrader::install_package()` returns a WP_Error object
     953         * when the source directory's file list cannot be retrieved.
     954         *
     955         * @ticket 61114
     956         *
     957         * @covers WP_Upgrader::install_package
     958         */
     959        public function test_install_package_should_return_wp_error_when_source_directory_file_list_cannot_be_retrieved() {
     960                self::$instance->generic_strings();
     961
     962                self::$upgrader_skin_mock
     963                                ->expects( $this->once() )
     964                                ->method( 'feedback' )
     965                                ->with( 'installing_package' );
     966
     967                self::$wp_filesystem_mock
     968                                ->expects( $this->once() )
     969                                ->method( 'dirlist' )
     970                                ->willReturn( false );
     971
     972                $args = array(
     973                        'source'      => '/',
     974                        'destination' => '/',
     975                );
     976
     977                $actual = self::$instance->install_package( $args );
     978
     979                $this->assertWPError(
     980                        $actual,
     981                        'WP_Upgrader::install_package() did not return a WP_Error object'
     982                );
     983
     984                $this->assertSame(
     985                        'source_read_failed',
     986                        $actual->get_error_code(),
     987                        'Unexpected WP_Error code'
     988                );
     989        }
     990
     991        /**
     992         * Tests that `WP_Upgrader::install_package()` returns a WP_Error object
     993         * when the source directory is filtered and its file list cannot be retrieved.
     994         *
     995         * @ticket 61114
     996         *
     997         * @covers WP_Upgrader::install_package
     998         *
     999         * @runInSeparateProcess
     1000         * @preserveGlobalState disabled
     1001         */
     1002        public function test_install_package_should_return_wp_error_when_a_filtered_source_directory_file_list_cannot_be_retrieved() {
     1003                define( 'FS_CHMOD_DIR', 0755 );
     1004
     1005                self::$instance->generic_strings();
     1006
     1007                self::$upgrader_skin_mock
     1008                                ->expects( $this->once() )
     1009                                ->method( 'feedback' )
     1010                                ->with( 'installing_package' );
     1011
     1012                $first_source = array(
     1013                        'subdir' => array(
     1014                                'name'  => 'subdir',
     1015                                'type'  => 'd',
     1016                                'files' => array( 'subfile.php' ),
     1017                        ),
     1018                );
     1019
     1020                self::$wp_filesystem_mock
     1021                                ->expects( $this->exactly( 2 ) )
     1022                                ->method( 'dirlist' )
     1023                                ->willReturn( $first_source, false );
     1024
     1025                $args = array(
     1026                        'source'      => '/',
     1027                        'destination' => '/',
     1028                );
     1029
     1030                // Filter the source to something else.
     1031                add_filter(
     1032                        'upgrader_source_selection',
     1033                        static function () {
     1034                                return '/not_original_source/';
     1035                        }
     1036                );
     1037
     1038                $actual = self::$instance->install_package( $args );
     1039
     1040                $this->assertWPError(
     1041                        $actual,
     1042                        'WP_Upgrader::install_package() did not return a WP_Error object'
     1043                );
     1044
     1045                $this->assertSame(
     1046                        'new_source_read_failed',
     1047                        $actual->get_error_code(),
     1048                        'Unexpected WP_Error code'
     1049                );
     1050        }
     1051
     1052        /**
    9521053         * Tests that `WP_Upgrader::install_package()` adds a trailing slash to
    9531054         * the source directory of a single file.
Note: See TracChangeset for help on using the changeset viewer.