Make WordPress Core

Changeset 61405


Ignore:
Timestamp:
12/24/2025 06:46:29 AM (8 months ago)
Author:
westonruter
Message:

Export: Fix fatal error when passing null to wxr_cdata() by casting passed value to string.

This ensures that wp_is_valid_utf8() does not cause a type error since it only accepts strings.

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

Follow-up to [60630].

Props hbhalodia, westonruter, desrosj, albigdd, jorbin.
See #38044.
Fixes #64347.

Location:
trunk
Files:
2 edited

Legend:

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

    r61369 r61405  
    240240         * @since 2.1.0
    241241         *
    242          * @param string $str String to wrap in XML CDATA tag.
     242         * @param string|null $str String to wrap in XML CDATA tag. May be null.
    243243         * @return string
    244244         */
    245245        function wxr_cdata( $str ) {
     246                $str = (string) $str;
     247
    246248                if ( ! wp_is_valid_utf8( $str ) ) {
    247249                        $str = utf8_encode( $str );
  • trunk/tests/phpunit/tests/admin/exportWp.php

    r61369 r61405  
    324324                $this->assertCount( $comment_count, $comment_tags, 'Export should include all comments when not filtered.' );
    325325        }
     326
     327        /**
     328         * Tests that export handles posts with NULL postmeta values without fatal errors.
     329         *
     330         * @ticket 64347
     331         */
     332        public function test_export_with_null_postmeta_values() {
     333                global $wpdb;
     334
     335                $post_id = self::factory()->post->create(
     336                        array(
     337                                'post_title'   => 'Test Post with NULL Meta',
     338                                'post_content' => 'Test content',
     339                                'post_type'    => 'post',
     340                        )
     341                );
     342
     343                // Add multiple types of postmeta values.
     344                add_post_meta( $post_id, 'string_meta', 'normal string' );
     345                add_post_meta( $post_id, 'numeric_string_meta', 123 );
     346                add_post_meta( $post_id, 'empty_string_meta', '' );
     347                add_post_meta(
     348                        $post_id,
     349                        'array_meta',
     350                        array(
     351                                'key' => 'value',
     352                        )
     353                );
     354
     355                // Directly insert NULL and non-string values into postmeta.
     356                $wpdb->insert(
     357                        $wpdb->postmeta,
     358                        array(
     359                                'post_id'    => $post_id,
     360                                'meta_key'   => 'null_meta',
     361                                'meta_value' => null,
     362                        ),
     363                        array( '%d', '%s', '%s' )
     364                );
     365
     366                $xml = $this->get_the_export(
     367                        array(
     368                                'content' => 'post',
     369                        )
     370                );
     371
     372                $this->assertNotFalse( $xml, 'Export should not fail with NULL postmeta values' );
     373                $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     374
     375                // Post should be present in export.
     376                $found_post = false;
     377                foreach ( $xml->channel->item as $item ) {
     378                        $wp_item = $item->children( 'wp', true );
     379                        if ( (int) $wp_item->post_id === $post_id ) {
     380                                $found_post = true;
     381                                break;
     382                        }
     383                }
     384
     385                $this->assertTrue( $found_post, 'Post with NULL metadata should be included in export' );
     386        }
     387
     388        /**
     389         * Tests that export handles comments with NULL values without fatal errors.
     390         *
     391         * @ticket 64347
     392         */
     393        public function test_export_with_null_comment_values() {
     394                global $wpdb;
     395
     396                $post_id = self::factory()->post->create(
     397                        array(
     398                                'post_title' => 'Test Post for Comments',
     399                                'post_type'  => 'post',
     400                        )
     401                );
     402
     403                $comment_id = self::factory()->comment->create(
     404                        array(
     405                                'comment_post_ID' => $post_id,
     406                                'comment_content' => 'Test comment',
     407                        )
     408                );
     409
     410                // Insert NULL comment meta.
     411                $wpdb->insert(
     412                        $wpdb->commentmeta,
     413                        array(
     414                                'comment_id' => $comment_id,
     415                                'meta_key'   => 'null_comment_meta',
     416                                'meta_value' => null,
     417                        ),
     418                        array( '%d', '%s', '%s' )
     419                );
     420
     421                $xml = $this->get_the_export(
     422                        array(
     423                                'content' => 'post',
     424                        )
     425                );
     426
     427                $this->assertNotFalse( $xml, 'Export should not fail with NULL comment meta values' );
     428                $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     429        }
     430
     431        /**
     432         * Tests that export handles term meta with NULL values without fatal errors.
     433         *
     434         * @ticket 64347
     435         */
     436        public function test_export_with_null_term_meta_values() {
     437                global $wpdb;
     438
     439                // Create term.
     440                $term = self::factory()->term->create(
     441                        array(
     442                                'taxonomy' => 'category',
     443                                'name'     => 'Test Category',
     444                        )
     445                );
     446
     447                $post_id = self::factory()->post->create(
     448                        array(
     449                                'post_title'  => 'Test Post with Category',
     450                                'post_type'   => 'post',
     451                                'post_status' => 'publish',
     452                        )
     453                );
     454
     455                wp_set_object_terms( $post_id, $term, 'category' );
     456
     457                // Insert NULL term meta.
     458                $wpdb->insert(
     459                        $wpdb->termmeta,
     460                        array(
     461                                'term_id'    => $term,
     462                                'meta_key'   => 'null_term_meta',
     463                                'meta_value' => null,
     464                        ),
     465                        array( '%d', '%s', '%s' )
     466                );
     467
     468                $xml = $this->get_the_export(
     469                        array(
     470                                'content' => 'all',
     471                        )
     472                );
     473
     474                $this->assertNotFalse( $xml, 'Export should not fail with NULL term meta values' );
     475                $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     476        }
    326477}
Note: See TracChangeset for help on using the changeset viewer.