Make WordPress Core

Opened 5 months ago

Last modified 5 months ago

#60276 new defect (bug)

Fatal error with unexpected string value for sticky_posts option

Reported by: mreishus's profile mreishus Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: General Keywords: reporter-feedback
Focuses: Cc:

Description

Summary:

Code in wp-include/blocks.php pulls out the option on line 1708:

$sticky = get_option( 'sticky_posts' );

Then assumes it is an array, when passing it into array_merge on line 1720:

$query['post__not_in'] = array_merge( $query['post__not_in'], $sticky );

This can cause a fatal error if the option is not set to an array:

Fatal error: Uncaught TypeError: array_merge(): Argument #2 must be of type array, string given 

Other parts of the code are defensive about the data coming from get_option( 'sticky_posts' ); , but this part is not.

Steps to Reproduce:

  • Use WP 6.4.2 and theme Twenty Twenty-Four Version: 1.0
  • Set your sticky_posts option to an empty string (an unexpected type)
MariaDB [wordpress]> select * from wp_options where option_name='sticky_posts';
+-----------+--------------+--------------+----------+
| option_id | option_name  | option_value | autoload |
+-----------+--------------+--------------+----------+
|        75 | sticky_posts | a:0:{}       | yes      |
+-----------+--------------+--------------+----------+
1 row in set (0.000 sec)

MariaDB [wordpress]> update wp_options set option_value='' where option_id=75;
Query OK, 1 row affected (0.012 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [wordpress]> select * from wp_options where option_name='sticky_posts';
+-----------+--------------+--------------+----------+
| option_id | option_name  | option_value | autoload |
+-----------+--------------+--------------+----------+
|        75 | sticky_posts |              | yes      |
+-----------+--------------+--------------+----------+
1 row in set (0.000 sec)
  • Go to site editor, patterns, "List of posts without images, 1 column" and duplicate it
  • Edit the duplicate
  • Navigate to the query loop block
  • On the right sidebar, turn off "Inherit query from template"
  • Change "Sticky Posts" from "Include" to "Exclude"
  • Attempt to save
  • A fatal error is triggered
  • Changing the "Sticky Posts" back to "Include" or changing the option value to a serialized array allows saving again

Attachments (1)

2024-01-17_11-17-fatal-error.png (135.8 KB) - added by mreishus 5 months ago.
Fatal error occuring when attempting to save in the site editor

Download all attachments as: .zip

Change History (5)

@mreishus
5 months ago

Fatal error occuring when attempting to save in the site editor

This ticket was mentioned in Slack in #core by jorbin. View the logs.


5 months ago

#2 follow-up: @jorbin
5 months ago

  • Keywords reporter-feedback added
  • Milestone changed from Awaiting Review to Future Release

Thanks for the report @mreishus. I'm curious if the unexpected value is something that core can cause or if it only happens through direct changes to the DB or errant custom code. Can you share a bit about how you found this initially?

It likely should be fixed but if it's not something core can cause on it's own, I think it lowers the priority.

#3 in reply to: ↑ 2 @mreishus
5 months ago

Replying to jorbin:

Thanks for the report @mreishus. I'm curious if the unexpected value is something that core can cause or if it only happens through direct changes to the DB or errant custom code. Can you share a bit about how you found this initially?

It likely should be fixed but if it's not something core can cause on it's own, I think it lowers the priority.

Sure, I found it while working on WordPress.com; a user had a site with the sticky_posts option set to an empty string. The type of site it is isn't allowed to run custom plugins or themes, so it must have been something in either core code or wp.com code.
I couldn't find anything in either that would set the option to this. However, this particular site was created 15 years ago, so it has ran on a lot of versions of code.
I can't say for certain it was done by core code, but it's a possibility. We've also found that the other parts of the code that read this option are defensive about unexpected return types. Here are some examples:

https://github.com/WordPress/wordpress-develop/blob/5815624ead21b4e105f3ddb09a9657ad84da654f/src/wp-includes/post.php#L2698-L2700
https://github.com/WordPress/wordpress-develop/blob/5815624ead21b4e105f3ddb09a9657ad84da654f/src/wp-admin/includes/post.php#L1288
https://github.com/WordPress/wordpress-develop/blob/5815624ead21b4e105f3ddb09a9657ad84da654f/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L304-L307

#4 @themearts
5 months ago

I can give it a shot. I think I can check to see wether the option is an empty string then don't merge it.

$querypost__not_in? = ($sticky !== && is_array($sticky)) ? array_merge( $querypost__not_in?, $sticky ) : $querypost__not_in?;

Have not tested the codes. Just an idea. Not sure why the [] don't display correctly in my comment.

The data stored in wp_options are serialized data so it is expected to return an array of data when deserialized.

Last edited 5 months ago by themearts (previous) (diff)
Note: See TracTickets for help on using tickets.