WordPress.org

Make WordPress Core

Ticket #28635: 28635.1.diff

File 28635.1.diff, 6.3 KB (added by westonruter, 5 years ago)

Fix order of operations in request validity check

  • src/wp-cron.php

    diff --git src/wp-cron.php src/wp-cron.php
    index 2b965dd..a3d757e 100644
     
    99 * @package WordPress
    1010 */
    1111
    12 ignore_user_abort(true);
     12ignore_user_abort( true );
    1313
    14 if ( !empty($_POST) || defined('DOING_AJAX') || defined('DOING_CRON') )
    15         die();
     14if ( defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) ) {
     15        die( 'doing_ajax_or_doing_cron' );
     16}
    1617
    1718/**
    1819 * Tell WordPress we are doing the CRON task.
    1920 *
    2021 * @var bool
    2122 */
    22 define('DOING_CRON', true);
     23define( 'DOING_CRON', true );
    2324
    24 if ( !defined('ABSPATH') ) {
     25if ( ! defined( 'ABSPATH' ) ) {
    2526        /** Set up WordPress environment */
    2627        require_once( dirname( __FILE__ ) . '/wp-load.php' );
    2728}
    2829
     30/**
     31 * Default handler for a WP Cron exit
     32 *
     33 * @param string $code
     34 */
     35function wp_cron_default_exit_handler( $code ) {
     36        do_action( 'wp_cron_response_close', $code );
     37        if ( 'bad_post_request_or_doing_ajax_or_doing_cron' === $code ) {
     38                $response = 400;
     39        } elseif ( 'empty_cron_array' === $code ) {
     40                $response = 204;
     41        } elseif ( 'no_scheduled_actions_due' === $code ) {
     42                $response = 204;
     43        } elseif ( 'cron_locked' === $code ) {
     44                $response = 403;
     45        } elseif ( 'cron_lock_check_fail' === $code ) {
     46                $response = 400;
     47        } elseif ( 'ok_exit_prematurely' === $code ) {
     48                $response = 200;
     49        } elseif ( 'ok' === $code ) {
     50                $response = 200;
     51        } else {
     52                $response = 500;
     53        }
     54        if ( ! headers_sent() ) {
     55                header( 'Content-Type: text/plain' );
     56                status_header( $response );
     57        }
     58        wp_die( $code, '', compact( $response ) );
     59}
     60
     61/**
     62 * @var string $wp_cron_exit_handler
     63 * @todo docs
     64 */
     65$wp_cron_exit_handler = apply_filters( 'wp_cron_exit_handler', 'wp_cron_default_exit_handler' );
     66
     67if ( ! empty( $_POST ) ) {
     68        $wp_cron_exit_handler( 'bad_post_request' );
     69}
     70
    2971// Uncached doing_cron transient fetch
    3072function _get_cron_lock() {
    3173        global $wpdb;
    function _get_cron_lock() { 
    3981                $value = wp_cache_get( 'doing_cron', 'transient', true );
    4082        } else {
    4183                $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron' ) );
    42                 if ( is_object( $row ) )
     84                if ( is_object( $row ) ) {
    4385                        $value = $row->option_value;
     86                }
    4487        }
    4588
    4689        return $value;
    4790}
    4891
    49 if ( false === $crons = _get_cron_array() )
    50         die();
     92if ( false === $crons = _get_cron_array() ) {
     93        $wp_cron_exit_handler( 'empty_cron_array' );
     94}
    5195
    5296$keys = array_keys( $crons );
    5397$gmt_time = microtime( true );
    5498
    55 if ( isset($keys[0]) && $keys[0] > $gmt_time )
    56         die();
     99if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) {
     100        $wp_cron_exit_handler( 'no_scheduled_actions_due' );
     101}
    57102
    58 $doing_cron_transient = get_transient( 'doing_cron');
     103$doing_cron_transient = get_transient( 'doing_cron' );
    59104
    60105// Use global $doing_wp_cron lock otherwise use the GET lock. If no lock, trying grabbing a new lock.
    61106if ( empty( $doing_wp_cron ) ) {
    62         if ( empty( $_GET[ 'doing_wp_cron' ] ) ) {
     107        if ( empty( $_GET['doing_wp_cron'] ) ) {
    63108                // Called from external script/job. Try setting a lock.
    64                 if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) )
    65                         return;
     109                if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) ) {
     110                        $wp_cron_exit_handler( 'cron_locked' );
     111                }
    66112                $doing_cron_transient = $doing_wp_cron = sprintf( '%.22F', microtime( true ) );
    67113                set_transient( 'doing_cron', $doing_wp_cron );
    68114        } else {
    69                 $doing_wp_cron = $_GET[ 'doing_wp_cron' ];
     115                $doing_wp_cron = $_GET['doing_wp_cron'];
    70116        }
    71117}
    72118
    73119// Check lock
    74 if ( $doing_cron_transient != $doing_wp_cron )
    75         return;
     120if ( $doing_cron_transient != $doing_wp_cron ) {
     121        $wp_cron_exit_handler( 'cron_lock_check_fail' );
     122}
    76123
     124/**
     125 * @todo docs
     126 */
     127do_action( 'wp_cron_before_crons_loop', $crons );
    77128foreach ( $crons as $timestamp => $cronhooks ) {
    78         if ( $timestamp > $gmt_time )
     129        if ( $timestamp > $gmt_time ) {
    79130                break;
     131        }
    80132
     133        /**
     134         * @todo docs
     135         */
     136        do_action( 'wp_cron_before_cronhooks_loop', $cronhooks );
    81137        foreach ( $cronhooks as $hook => $keys ) {
    82138
     139                /**
     140                 * @todo docs
     141                 */
     142                do_action( 'wp_cron_before_keys_loop', $keys );
    83143                foreach ( $keys as $k => $v ) {
    84144
    85145                        $schedule = $v['schedule'];
    86146
    87147                        if ( $schedule != false ) {
    88                                 $new_args = array($timestamp, $schedule, $hook, $v['args']);
    89                                 call_user_func_array('wp_reschedule_event', $new_args);
     148                                $new_args = array( $timestamp, $schedule, $hook, $v['args'] );
     149                                call_user_func_array( 'wp_reschedule_event', $new_args );
    90150                        }
    91151
    92152                        wp_unschedule_event( $timestamp, $hook, $v['args'] );
    93153
    94154                        /**
     155                         * @todo docs
     156                         */
     157                        do_action( 'wp_cron_before_hook', $hook, $v['args'], $schedule, $timestamp );
     158
     159                        /**
    95160                         * Fires scheduled events.
    96161                         *
    97162                         * @internal
    foreach ( $crons as $timestamp => $cronhooks ) { 
    100165                         * @param string $hook Name of the hook that was scheduled to be fired.
    101166                         * @param array  $args The arguments to be passed to the hook.
    102167                         */
    103                         do_action_ref_array( $hook, $v['args'] );
     168                        do_action_ref_array( $hook, $v['args'] );
     169
     170                        /**
     171                         * @todo docs
     172                         */
     173                        do_action( 'wp_cron_after_hook', $hook, $v['args'], $schedule, $timestamp );
    104174
    105175                        // If the hook ran too long and another cron process stole the lock, quit.
    106                         if ( _get_cron_lock() != $doing_wp_cron )
    107                                 return;
     176                        if ( _get_cron_lock() != $doing_wp_cron ) {
     177                                $wp_cron_exit_handler( 'ok_exit_prematurely' );
     178                        }
    108179                }
     180
     181                /**
     182                 * @todo docs
     183                 */
     184                do_action( 'wp_cron_after_keys_loop', $keys );
    109185        }
     186
     187        /**
     188         * @todo docs
     189         */
     190        do_action( 'wp_cron_after_cronhooks_loop', $cronhooks );
    110191}
     192/**
     193 * @todo docs
     194 */
     195do_action( 'wp_cron_after_crons_loop', $crons );
    111196
    112 if ( _get_cron_lock() == $doing_wp_cron )
     197if ( _get_cron_lock() == $doing_wp_cron ) {
    113198        delete_transient( 'doing_cron' );
     199}
    114200
    115 die();
     201$wp_cron_exit_handler( 'ok' );
  • src/wp-includes/functions.php

    diff --git src/wp-includes/functions.php src/wp-includes/functions.php
    index 33ace42..bc305e8 100644
    function wp_nonce_ays( $action ) { 
    22422242 * @param string|array $args Optional arguments to control behavior.
    22432243 */
    22442244function wp_die( $message = '', $title = '', $args = array() ) {
    2245         if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
     2245        if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
    22462246                /**
    22472247                 * Filter callback for killing WordPress execution for AJAX requests.
    22482248                 *