Make WordPress Core


Ignore:
Timestamp:
10/29/2024 03:36:56 PM (5 weeks ago)
Author:
SergeyBiryukov
Message:

Comments: Use a more precise check for disallowed keys on filtered comment data.

The previous approach of running wp_allow_comment() twice could have unintended consequences, e.g. the check_comment_flood action was also triggered twice, which might lead to false-positive identification of comment flood in case there is some custom callback hooked to it, which is not expecting identical data seeing twice.

This commit introduces a new function, wp_check_comment_data(), to specifically check for disallowed content before and after comment data is filtered.

Follow-up to [59267].

Props david.binda, SergeyBiryukov.
See #61827.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/comment.php

    r59291 r59319  
    774774    }
    775775
    776     if ( ! empty( $commentdata['user_id'] ) ) {
    777         $user        = get_userdata( $commentdata['user_id'] );
    778         $post_author = $wpdb->get_var(
    779             $wpdb->prepare(
    780                 "SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",
    781                 $commentdata['comment_post_ID']
    782             )
    783         );
    784     }
    785 
    786     if ( isset( $user ) && ( $commentdata['user_id'] == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
    787         // The author and the admins get respect.
    788         $approved = 1;
    789     } else {
    790         // Everyone else's comments will be checked.
    791         if ( check_comment(
    792             $commentdata['comment_author'],
    793             $commentdata['comment_author_email'],
    794             $commentdata['comment_author_url'],
    795             $commentdata['comment_content'],
    796             $commentdata['comment_author_IP'],
    797             $commentdata['comment_agent'],
    798             $commentdata['comment_type']
    799         ) ) {
    800             $approved = 1;
    801         } else {
    802             $approved = 0;
    803         }
    804 
    805         if ( wp_check_comment_disallowed_list(
    806             $commentdata['comment_author'],
    807             $commentdata['comment_author_email'],
    808             $commentdata['comment_author_url'],
    809             $commentdata['comment_content'],
    810             $commentdata['comment_author_IP'],
    811             $commentdata['comment_agent']
    812         ) ) {
    813             $approved = EMPTY_TRASH_DAYS ? 'trash' : 'spam';
    814         }
    815     }
    816 
    817     /**
    818      * Filters a comment's approval status before it is set.
    819      *
    820      * @since 2.1.0
    821      * @since 4.9.0 Returning a WP_Error value from the filter will short-circuit comment insertion
    822      *              and allow skipping further processing.
    823      *
    824      * @param int|string|WP_Error $approved    The approval status. Accepts 1, 0, 'spam', 'trash',
    825      *                                         or WP_Error.
    826      * @param array               $commentdata Comment data.
    827      */
    828     return apply_filters( 'pre_comment_approved', $approved, $commentdata );
     776    return wp_check_comment_data( $commentdata );
    829777}
    830778
     
    12911239
    12921240    return true;
     1241}
     1242
     1243/**
     1244 * Checks whether comment data passes internal checks or has disallowed content.
     1245 *
     1246 * @since 6.7.0
     1247 *
     1248 * @global wpdb $wpdb WordPress database abstraction object.
     1249 *
     1250 * @param array $comment_data Array of arguments for inserting a comment.
     1251 * @return int|string|WP_Error The approval status on success (0|1|'spam'|'trash'),
     1252  *                            WP_Error otherwise.
     1253 */
     1254function wp_check_comment_data( $comment_data ) {
     1255    global $wpdb;
     1256
     1257    if ( ! empty( $comment_data['user_id'] ) ) {
     1258        $user        = get_userdata( $comment_data['user_id'] );
     1259        $post_author = $wpdb->get_var(
     1260            $wpdb->prepare(
     1261                "SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",
     1262                $comment_data['comment_post_ID']
     1263            )
     1264        );
     1265    }
     1266
     1267    if ( isset( $user ) && ( $comment_data['user_id'] == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
     1268        // The author and the admins get respect.
     1269        $approved = 1;
     1270    } else {
     1271        // Everyone else's comments will be checked.
     1272        if ( check_comment(
     1273            $comment_data['comment_author'],
     1274            $comment_data['comment_author_email'],
     1275            $comment_data['comment_author_url'],
     1276            $comment_data['comment_content'],
     1277            $comment_data['comment_author_IP'],
     1278            $comment_data['comment_agent'],
     1279            $comment_data['comment_type']
     1280        ) ) {
     1281            $approved = 1;
     1282        } else {
     1283            $approved = 0;
     1284        }
     1285
     1286        if ( wp_check_comment_disallowed_list(
     1287            $comment_data['comment_author'],
     1288            $comment_data['comment_author_email'],
     1289            $comment_data['comment_author_url'],
     1290            $comment_data['comment_content'],
     1291            $comment_data['comment_author_IP'],
     1292            $comment_data['comment_agent']
     1293        ) ) {
     1294            $approved = EMPTY_TRASH_DAYS ? 'trash' : 'spam';
     1295        }
     1296    }
     1297
     1298    /**
     1299     * Filters a comment's approval status before it is set.
     1300     *
     1301     * @since 2.1.0
     1302     * @since 4.9.0 Returning a WP_Error value from the filter will short-circuit comment insertion
     1303     *              and allow skipping further processing.
     1304     *
     1305     * @param int|string|WP_Error $approved    The approval status. Accepts 1, 0, 'spam', 'trash',
     1306     *                                         or WP_Error.
     1307     * @param array               $commentdata Comment data.
     1308     */
     1309    return apply_filters( 'pre_comment_approved', $approved, $comment_data );
    12931310}
    12941311
     
    22802297    $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );
    22812298
     2299    if ( is_wp_error( $commentdata['comment_approved'] ) ) {
     2300        return $commentdata['comment_approved'];
     2301    }
     2302
    22822303    $commentdata = wp_filter_comment( $commentdata );
    22832304
    22842305    if ( ! in_array( $commentdata['comment_approved'], array( 'trash', 'spam' ), true ) ) {
    22852306        // Validate the comment again after filters are applied to comment data.
    2286         $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );
     2307        $commentdata['comment_approved'] = wp_check_comment_data( $commentdata );
    22872308    }
    22882309
Note: See TracChangeset for help on using the changeset viewer.