[wp-trac] [WordPress Trac] #64347: Fatal error when `wxr_cdata()` is called with non-string value

WordPress Trac noreply at wordpress.org
Wed Dec 17 23:33:22 UTC 2025


#64347: Fatal error when `wxr_cdata()` is called with non-string value
----------------------------------------+---------------------
 Reporter:  desrosj                     |       Owner:  (none)
     Type:  defect (bug)                |      Status:  new
 Priority:  normal                      |   Milestone:  6.9.1
Component:  Export                      |     Version:  6.9
 Severity:  normal                      |  Resolution:
 Keywords:  has-patch needs-unit-tests  |     Focuses:
----------------------------------------+---------------------

Comment (by westonruter):

 In looking at the original error stack trace, the source of the error is
 at [https://github.com/WordPress/wordpress-
 develop/blob/5df78618d61c91194c40223cfc07f2eb6d01ac96/src/wp-
 admin/includes/export.php#L682 /wp-admin/includes/export.php(682)]:

 {{{#!php
 <wp:meta_value><?php echo wxr_cdata( $meta->meta_value );
 ?></wp:meta_value>
 }}}

 The problem is that `$meta->meta_value` may be `null` here, although I'm
 not sure why. The `$meta` variable is coming iterating over this array:

 {{{#!php
 <?php
 $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE
 post_id = %d", $post->ID ) )
 }}}

 It appears the issue is that the `wp_postmeta.meta_value` column is
 defined as a `LONGTEXT` which may also be `NULL`
 ([https://github.com/WordPress/wordpress-
 develop/blob/5df78618d61c91194c40223cfc07f2eb6d01ac96/src/wp-
 admin/includes/schema.php#L150-L158 source]):

 {{{
 CREATE TABLE $wpdb->postmeta (
         meta_id bigint(20) unsigned NOT NULL auto_increment,
         post_id bigint(20) unsigned NOT NULL default '0',
         meta_key varchar(255) default NULL,
         meta_value longtext,
         PRIMARY KEY  (meta_id),
         KEY post_id (post_id),
         KEY meta_key (meta_key($max_index_length))
 ) $charset_collate;
 }}}

 According to the [https://dev.mysql.com/doc/refman/8.4/en/create-
 table.html MySQL reference]:

 > If neither NULL nor NOT NULL is specified, the column is treated as
 though NULL had been specified.

 So this appears to be the source of the non-string value.

 It didn't cause an error in WordPress 6.8 because `wxr_cdata()` was
 defined as:

 {{{#!php
 <?php
 function wxr_cdata( $str ) {
         if ( ! seems_utf8( $str ) ) {
                 $str = utf8_encode( $str );
         }
         // $str = ent2ncr(esc_html($str));
         $str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str )
 . ']]>';

         return $str;
 }
 }}}

 Whereas in WP 6.9 it is:

 {{{#!php
 <?php
 function wxr_cdata( $str ) {
         if ( ! wp_is_valid_utf8( $str ) ) {
                 $str = utf8_encode( $str );
         }
         // $str = ent2ncr(esc_html($str));
         $str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str )
 . ']]>';

         return $str;
 }
 }}}

 The difference is that `seems_utf8()` didn't have any PHP type defined for
 the `$str` argument:

 {{{
 function seems_utf8( $str )
 }}}

 Whereas `wp_is_valid_utf8` does:

 {{{
 function wp_is_valid_utf8( string $string )
 }}}

 So to fix this issue, it seems casting the `$str` to a `string` will
 preserve the original behavior which would happen implicitly when `$str`
 is passed through `str_replace()`. Note that in PHP 8.1 this would have
 caused a deprecation error already anyway when the `$str` was passed into
 `seems_utf8()` in 6.8:

 > Deprecated: strlen(): Passing null to parameter #1 ($string) of type
 string is deprecated in /var/www/src/wp-includes/formatting.php on line
 888

 The deprecation in 6.8 has become a fatal error in 6.9 due to the use of a
 PHP type for the `$str` param.

 All this to say, I think at the beginning of `wxr_cdata()` can simply do
 this:

 {{{#!php
 <?php
 if ( is_scalar( $str ) ) {
         $str = (string) $str;
 }
 }}}

 If, by chance, a non-scalar value (an array or object) is passed in
 erroneously, then this will cause a PHP fatal error in the same way as
 would be happening in 6.8 already.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64347#comment:13>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list