Skip to content

Commit 8aa02bf

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]. Reviewed-by jorbin. Merges [61405] to the 6.9 branch. Props hbhalodia, westonruter, desrosj, albigdd, jorbin. See #38044. Fixes #64347. git-svn-id: https://develop.svn.wordpress.org/branches/6.9@61540 602fd350-edb4-49c9-b593-d223f7449a82
1 parent f815929 commit 8aa02bf

2 files changed

Lines changed: 154 additions & 1 deletion

File tree

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
@@ -290,4 +290,155 @@ private function populate_args_post_authors( array &$args, $expected_ids ) {
290290
$post_ids_key = $expected_ids[0];
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
}

0 commit comments

Comments
 (0)