Make WordPress Core

Changeset 61540


Ignore:
Timestamp:
01/27/2026 10:12:40 PM (4 weeks ago)
Author:
jorbin
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].

Reviewed-by jorbin.
Merges [61405] to the 6.9 branch.

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

Location:
branches/6.9
Files:
2 edited

Legend:

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

    r60632 r61540  
    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 );
  • branches/6.9/tests/phpunit/tests/admin/exportWp.php

    r57681 r61540  
    291291        $args['author'] = self::$post_ids[ $post_ids_key ]['post_author'];
    292292    }
     293
     294    /**
     295     * Tests that export handles posts with NULL postmeta values without fatal errors.
     296     *
     297     * @ticket 64347
     298     */
     299    public function test_export_with_null_postmeta_values() {
     300        global $wpdb;
     301
     302        $post_id = self::factory()->post->create(
     303            array(
     304                'post_title'   => 'Test Post with NULL Meta',
     305                'post_content' => 'Test content',
     306                'post_type'    => 'post',
     307            )
     308        );
     309
     310        // Add multiple types of postmeta values.
     311        add_post_meta( $post_id, 'string_meta', 'normal string' );
     312        add_post_meta( $post_id, 'numeric_string_meta', 123 );
     313        add_post_meta( $post_id, 'empty_string_meta', '' );
     314        add_post_meta(
     315            $post_id,
     316            'array_meta',
     317            array(
     318                'key' => 'value',
     319            )
     320        );
     321
     322        // Directly insert NULL and non-string values into postmeta.
     323        $wpdb->insert(
     324            $wpdb->postmeta,
     325            array(
     326                'post_id'    => $post_id,
     327                'meta_key'   => 'null_meta',
     328                'meta_value' => null,
     329            ),
     330            array( '%d', '%s', '%s' )
     331        );
     332
     333        $xml = $this->get_the_export(
     334            array(
     335                'content' => 'post',
     336            )
     337        );
     338
     339        $this->assertNotFalse( $xml, 'Export should not fail with NULL postmeta values' );
     340        $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     341
     342        // Post should be present in export.
     343        $found_post = false;
     344        foreach ( $xml->channel->item as $item ) {
     345            $wp_item = $item->children( 'wp', true );
     346            if ( (int) $wp_item->post_id === $post_id ) {
     347                $found_post = true;
     348                break;
     349            }
     350        }
     351
     352        $this->assertTrue( $found_post, 'Post with NULL metadata should be included in export' );
     353    }
     354
     355    /**
     356     * Tests that export handles comments with NULL values without fatal errors.
     357     *
     358     * @ticket 64347
     359     */
     360    public function test_export_with_null_comment_values() {
     361        global $wpdb;
     362
     363        $post_id = self::factory()->post->create(
     364            array(
     365                'post_title' => 'Test Post for Comments',
     366                'post_type'  => 'post',
     367            )
     368        );
     369
     370        $comment_id = self::factory()->comment->create(
     371            array(
     372                'comment_post_ID' => $post_id,
     373                'comment_content' => 'Test comment',
     374            )
     375        );
     376
     377        // Insert NULL comment meta.
     378        $wpdb->insert(
     379            $wpdb->commentmeta,
     380            array(
     381                'comment_id' => $comment_id,
     382                'meta_key'   => 'null_comment_meta',
     383                'meta_value' => null,
     384            ),
     385            array( '%d', '%s', '%s' )
     386        );
     387
     388        $xml = $this->get_the_export(
     389            array(
     390                'content' => 'post',
     391            )
     392        );
     393
     394        $this->assertNotFalse( $xml, 'Export should not fail with NULL comment meta values' );
     395        $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     396    }
     397
     398    /**
     399     * Tests that export handles term meta with NULL values without fatal errors.
     400     *
     401     * @ticket 64347
     402     */
     403    public function test_export_with_null_term_meta_values() {
     404        global $wpdb;
     405
     406        // Create term.
     407        $term = self::factory()->term->create(
     408            array(
     409                'taxonomy' => 'category',
     410                'name'     => 'Test Category',
     411            )
     412        );
     413
     414        $post_id = self::factory()->post->create(
     415            array(
     416                'post_title'  => 'Test Post with Category',
     417                'post_type'   => 'post',
     418                'post_status' => 'publish',
     419            )
     420        );
     421
     422        wp_set_object_terms( $post_id, $term, 'category' );
     423
     424        // Insert NULL term meta.
     425        $wpdb->insert(
     426            $wpdb->termmeta,
     427            array(
     428                'term_id'    => $term,
     429                'meta_key'   => 'null_term_meta',
     430                'meta_value' => null,
     431            ),
     432            array( '%d', '%s', '%s' )
     433        );
     434
     435        $xml = $this->get_the_export(
     436            array(
     437                'content' => 'all',
     438            )
     439        );
     440
     441        $this->assertNotFalse( $xml, 'Export should not fail with NULL term meta values' );
     442        $this->assertGreaterThan( 0, count( $xml->channel->item ), 'Export should contain items' );
     443    }
    293444}
Note: See TracChangeset for help on using the changeset viewer.