Make WordPress Core

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#53950 closed defect (bug) (fixed)

`wp_schedule_single_event()` may add incorrectly populate the cron array.

Reported by: peterwilsoncc's profile peterwilsoncc Owned by: hellofromtonya's profile hellofromTonya
Milestone: 5.9 Priority: normal
Severity: normal Version: 5.2
Component: Cron API Keywords: has-patch has-unit-tests
Focuses: Cc:

Description

In [44917] for #44818 wp_schedule_single_event() started casting the result of _get_cron_array() to an array.

As _get_cron_array() can return false if the option does not exist/is of incorrect type then this can result in a malformed cron array (see #53940 for discussion).

If the getter returns false, wp_schedule_single_event() will set the cron array to [ false ]. The single event being scheduled will then be appended to the malformed cron array.

This is an edge case as it relies on either the cron option to be malformed or deleted. WordPress populates the cron array with recurring events during installation and wp_schedule_event() doesn't share this problem.

Change History (15)

This ticket was mentioned in PR #1598 on WordPress/wordpress-develop by jrfnl.


3 years ago
#1

  • Keywords has-patch has-unit-tests added

### Tests: add test for wp_schedule_single_event() when there are no scheduled crons

This tests proves a bug introduced in Trac 44818 / [44917].

### Cron: fix bug in wp_schedule_single_event()

In wp_schedule_single_event(), the cron info array is retrieved via a call to _get_cron_array() and straight away cast to an array, but as the documentation for that function (correctly) states, the return type of that function is array|false, where false is returned for a site where no cron jobs have been scheduled (yet).

In the case that _get_cron_array() would return false, this would now unintentionally create an array with a single entry with key 0 and as the value false.

This is a bug. Fixed now by adding validation to the output of _get_cron_array() and initializing $crons to an empty array if false was returned.

Note: this may need an upgrade routine to be added to clean existing cron arrays in which this false entry was inadvertently introduced.

Ref: https://developer.wordpress.org/reference/functions/_get_cron_array/

### To do:

  • [x] Open Trac ticket
  • [x] Update @ticket tag in the test with the trac ticket number
  • [x] Add link to the Trac ticket to this PR & set it to "ready for review"

Trac ticket: https://core.trac.wordpress.org/ticket/53950

jrfnl commented on PR #1598:


3 years ago
#2

Thanks @peterwilsoncc. Updated the test to contain the right ticket number and marked ready for review now.

#3 @jrf
3 years ago

  • Milestone changed from Awaiting Review to 5.9

#4 @mukesh27
3 years ago

  • Keywords commit added

Thanks for the PR. It looks fine to me.

Marking this ticket for commit

#5 follow-up: @jrf
3 years ago

For visibility, let me make sure this remark I made in the PR description does not get lost:

Note: this may need an upgrade routine to be added to clean existing cron arrays in which this false entry was inadvertently introduced.

Opinions whether or not this is needed welcome.

peterwilsoncc commented on PR #1598:


3 years ago
#6

Note: this may need an upgrade routine to be added to clean existing cron arrays in which this false entry was inadvertently introduced.

BTW, I am still considering this thus my lack of opinion in the review.

As it's an edge case bug, my inclination is to check for false in wp_upgrade() and remove it if necessary rather than a cron array upgrade routine and version update.

I need to think over the pros and cons over the next 24 hours or so.

#7 @mukesh27
3 years ago

  • Keywords commit removed

This ticket was mentioned in PR #1605 on WordPress/wordpress-develop by peterwilsoncc.


3 years ago
#8

https://core.trac.wordpress.org/ticket/53950

Follow up to PR #1598 to clean the cron array during the next version update.

As the cron array containing false is an edge case I decided cleaning it can wait until the next time sites need to run a DB upgrade rather than running it as part of the cron getter and changing the version it contains.

#9 in reply to: ↑ 5 @peterwilsoncc
3 years ago

Replying to jrf:

For visibility, let me make sure this remark I made in the PR description does not get lost:

Note: this may need an upgrade routine to be added to clean existing cron arrays in which this false entry was inadvertently introduced.

Opinions whether or not this is needed welcome.

I considered this overnight and decided to do it as part of the global database upgrade routine. There's a very slim chance this has happened on sites and having the false in there isn't a big problem so I figured it's okay not to do it as part of a cron array upgrade.

I've linked a pull request to this ticket to go in with @jrf's.

peterwilsoncc commented on PR #1598:


3 years ago
#10

Tonya asked if this is ready for commit, as we're going to discuss an upgrade routine in https://core.trac.wordpress.org/ticket/34913 I've suggested commit be held for a few days.

JRF and I are discussing 34913, which will need an upgrade routine, so the outcome of that discussion may affect the upgrade/clean up for this ticket.

#11 @hellofromTonya
3 years ago

  • Owner set to hellofromTonya
  • Resolution set to fixed
  • Status changed from new to closed

In 51916:

Cron: Fix malformed cron array in wp_schedule_single_event() when _get_cron_array() returns false.

In wp_schedule_single_event(), the cron info array is retrieved via a call to _get_cron_array() and straight away cast to an array. But as the documentation for that function (correctly) states, the return type of that function is array|false, where false is returned for a site where no cron jobs have been scheduled (yet).

In the case that _get_cron_array() would return false, this would now unintentionally create an array with a single entry with key 0 and as the value false.

This is a bug. Fixed now by adding validation to the output of _get_cron_array() and initializing $crons to an empty array if false was returned.

Tests added first to prove the bug (a) was introduced in #44818 [44917] and (b) is now fixed.

Follow-up to [44917].

Props jrf, peterwilsoncc.
Fixes #53950.

hellofromtonya commented on PR #1598:


3 years ago
#12

Committed via changeset 51916.

#13 @hellofromTonya
3 years ago

In 51917:

Cron: Remove errant false values in cron array when upgrading to 5.9+.

[51916] fixed a bug where array( false ) was added to the cron array when _get_cron_array() returned false.

This commit:

  • Removes any false values from the cron array when upgrading to 5.9+.
  • Bumps the database version.

Follow-up to [44917], [51916].

Props peterwilsoncc, jrf.
See #53950.

hellofromtonya commented on PR #1605:


3 years ago
#14

Committed via changeset 51917.

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


3 years ago

Note: See TracTickets for help on using tickets.