Skip to content

Commit 814279b

Browse files
committed
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 #10595 Follow-up to [60630]. Props hbhalodia, westonruter, desrosj, albigdd, jorbin. See #38044. Fixes #64347. git-svn-id: https://develop.svn.wordpress.org/trunk@61405 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 63e679c commit 814279b

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

src/wp-admin/includes/export.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,12 @@ function export_wp( $args = array() ) {
239239
*
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 );
248250
}

tests/phpunit/tests/admin/exportWp.php

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,155 @@ public function test_export_wp_includes_comments_when_not_filtered() {
323323
$comment_tags = $xml_obj->xpath( '//wp:comment' );
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
}

0 commit comments

Comments
 (0)