Make WordPress Core

Changeset 63580


Ignore:
Timestamp:
09/10/2026 11:18:52 AM (5 weeks ago)
Author:
jonsurrell
Message:

I18N: Validate cached translation file lists.

Prevent possible fatal errors on bad cached values by validating the caches is an array of strings.

Developed in: ​https://github.com/WordPress/wordpress-develop/pull/13429

Props josephscott, jonsurrell.
Fixes #66063.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-textdomain-registry.php

    r63362 r63580  
    209209                $cache_key = md5( $path );
    210210                $files     = wp_cache_get( $cache_key, 'translation_files' );
     211
     212                /*
     213                 * Verify that the cached value is an array and that all entries in that array
     214                 * are strings.
     215                 */
     216                if ( ! is_array( $files ) || array_filter( $files, 'is_string' ) !== $files ) {
     217                        $files = false;
     218                }
    211219
    212220                if ( false === $files ) {
  • trunk/tests/phpunit/tests/l10n/wpTextdomainRegistry.php

    r63362 r63580  
    110110                $this->assertEmpty( $result );
    111111                $this->assertFalse( $cache );
     112        }
     113
     114        /**
     115         * A cached value that is not an array of strings is discarded and replaced
     116         * by a fresh lookup.
     117         *
     118         * @ticket 66063
     119         *
     120         * @covers ::get_language_files_from_path
     121         *
     122         * @dataProvider data_get_language_files_from_path_ignores_invalid_cached_values
     123         *
     124         * @param mixed $cached_value Value seeded into the cache.
     125         */
     126        public function test_get_language_files_from_path_ignores_invalid_cached_values( $cached_value ): void {
     127                $path      = WP_LANG_DIR . '/plugins/';
     128                $cache_key = md5( $path );
     129
     130                wp_cache_set( $cache_key, $cached_value, 'translation_files' );
     131
     132                $result = $this->instance->get_language_files_from_path( $path );
     133
     134                $this->assertIsArray( $result, 'An array should be returned' );
     135                $this->assertNotEmpty( $result, 'The files should have been looked up instead of using the cached value' );
     136                foreach ( $result as $file ) {
     137                        $this->assertIsString( $file, 'All returned entries should be strings' );
     138                }
     139                $this->assertSame(
     140                        $result,
     141                        wp_cache_get( $cache_key, 'translation_files' ),
     142                        'The invalid cached value should have been replaced'
     143                );
     144        }
     145
     146        /**
     147         * Data provider.
     148         *
     149         * @return array[]
     150         */
     151        public static function data_get_language_files_from_path_ignores_invalid_cached_values(): array {
     152                return array(
     153                        'string'                => array( 'not-an-array' ),
     154                        'integer'               => array( 1 ),
     155                        'null'                  => array( null ),
     156                        'object'                => array( (object) array( WP_LANG_DIR . '/plugins/foo-de_DE.mo' ) ),
     157                        'array with an array'   => array( array( WP_LANG_DIR . '/plugins/foo-de_DE.mo', array( 'bar-de_DE.mo' ) ) ),
     158                        'array with an integer' => array( array( WP_LANG_DIR . '/plugins/foo-de_DE.mo', 1 ) ),
     159                        'array with null'       => array( array( null ) ),
     160                );
     161        }
     162
     163        /**
     164         * An empty array is a valid cached result for a directory without translation
     165         * files and must not cause a new lookup.
     166         *
     167         * @ticket 66063
     168         *
     169         * @covers ::get_language_files_from_path
     170         */
     171        public function test_get_language_files_from_path_keeps_cached_empty_array(): void {
     172                $path = WP_LANG_DIR . '/plugins/';
     173
     174                wp_cache_set( md5( $path ), array(), 'translation_files' );
     175
     176                $this->assertSame(
     177                        array(),
     178                        $this->instance->get_language_files_from_path( $path ),
     179                        'A cached empty array should be returned without looking up the files'
     180                );
    112181        }
    113182
Note: See TracChangeset for help on using the changeset viewer.