General: Fix problematic string to array parsing.

WordPress has historically often used code like `preg_split( '/[\s,]+/', $var )` to parse a string of comma-separated values into an array. However, this approach was causing an empty string to not be parsed into an empty array as expected, but rather into an array with the empty string as its sole element.

This was among other areas causing problems in the REST API where passing an empty request parameter could cause that request to fail because, instead of it being ignored, that parameter would be compared against the valid values for it, which typically do not include an empty string.

Props david.binda, sstoqnov.
Fixes #43977.

Built from https://develop.svn.wordpress.org/trunk@44546


git-svn-id: http://core.svn.wordpress.org/trunk@44377 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Felix Arntz 2019-01-10 21:06:49 +00:00
parent 0b5beabd36
commit a71d208785
7 changed files with 43 additions and 39 deletions

View File

@ -171,13 +171,13 @@ function get_bookmarks( $args = '' ) {
$r['exclude'] = ''; //ignore exclude, category, and category_name params if using include
$r['category'] = '';
$r['category_name'] = '';
$inclinks = preg_split( '/[\s,]+/', $r['include'] );
$inclinks = wp_parse_id_list( $r['include'] );
if ( count( $inclinks ) ) {
foreach ( $inclinks as $inclink ) {
if ( empty( $inclusions ) ) {
$inclusions = ' AND ( link_id = ' . intval( $inclink ) . ' ';
$inclusions = ' AND ( link_id = ' . $inclink . ' ';
} else {
$inclusions .= ' OR link_id = ' . intval( $inclink ) . ' ';
$inclusions .= ' OR link_id = ' . $inclink . ' ';
}
}
}
@ -188,13 +188,13 @@ function get_bookmarks( $args = '' ) {
$exclusions = '';
if ( ! empty( $r['exclude'] ) ) {
$exlinks = preg_split( '/[\s,]+/', $r['exclude'] );
$exlinks = wp_parse_id_list( $r['exclude'] );
if ( count( $exlinks ) ) {
foreach ( $exlinks as $exlink ) {
if ( empty( $exclusions ) ) {
$exclusions = ' AND ( link_id <> ' . intval( $exlink ) . ' ';
$exclusions = ' AND ( link_id <> ' . $exlink . ' ';
} else {
$exclusions .= ' AND link_id <> ' . intval( $exlink ) . ' ';
$exclusions .= ' AND link_id <> ' . $exlink . ' ';
}
}
}
@ -223,13 +223,13 @@ function get_bookmarks( $args = '' ) {
$category_query = '';
$join = '';
if ( ! empty( $r['category'] ) ) {
$incategories = preg_split( '/[\s,]+/', $r['category'] );
$incategories = wp_parse_id_list( $r['category'] );
if ( count( $incategories ) ) {
foreach ( $incategories as $incat ) {
if ( empty( $category_query ) ) {
$category_query = ' AND ( tt.term_id = ' . intval( $incat ) . ' ';
$category_query = ' AND ( tt.term_id = ' . $incat . ' ';
} else {
$category_query .= ' OR tt.term_id = ' . intval( $incat ) . ' ';
$category_query .= ' OR tt.term_id = ' . $incat . ' ';
}
}
}

View File

@ -482,9 +482,11 @@ class WP_Comment_Query {
// 'status' accepts an array or a comma-separated string.
$status_clauses = array();
$statuses = $this->query_vars['status'];
if ( ! is_array( $statuses ) ) {
$statuses = preg_split( '/[\s,]+/', $statuses );
$statuses = wp_parse_list( $this->query_vars['status'] );
// Empty 'status' should be interpreted as 'all'.
if ( empty( $statuses ) ) {
$statuses = array( 'all' );
}
// 'any' overrides other statuses.
@ -517,14 +519,10 @@ class WP_Comment_Query {
// User IDs or emails whose unapproved comments are included, regardless of $status.
if ( ! empty( $this->query_vars['include_unapproved'] ) ) {
$include_unapproved = $this->query_vars['include_unapproved'];
$include_unapproved = wp_parse_list( $this->query_vars['include_unapproved'] );
// Accepts arrays or comma-separated strings.
if ( ! is_array( $include_unapproved ) ) {
$include_unapproved = preg_split( '/[\s,]+/', $include_unapproved );
}
$unapproved_ids = $unapproved_emails = array();
$unapproved_ids = array();
$unapproved_emails = array();
foreach ( $include_unapproved as $unapproved_identifier ) {
// Numeric values are assumed to be user ids.
if ( is_numeric( $unapproved_identifier ) ) {

View File

@ -3822,6 +3822,22 @@ function wp_parse_args( $args, $defaults = '' ) {
return $r;
}
/**
* Cleans up an array, comma- or space-separated list of scalar values.
*
* @since 5.1.0
*
* @param array|string $list List of values.
* @return array Sanitized array of values.
*/
function wp_parse_list( $list ) {
if ( ! is_array( $list ) ) {
return preg_split( '/[\s,]+/', $list, -1, PREG_SPLIT_NO_EMPTY );
}
return $list;
}
/**
* Clean up an array, comma- or space-separated list of IDs.
*
@ -3831,9 +3847,7 @@ function wp_parse_args( $args, $defaults = '' ) {
* @return array Sanitized array of IDs.
*/
function wp_parse_id_list( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
$list = wp_parse_list( $list );
return array_unique( array_map( 'absint', $list ) );
}
@ -3847,15 +3861,9 @@ function wp_parse_id_list( $list ) {
* @return array Sanitized array of slugs.
*/
function wp_parse_slug_list( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
$list = wp_parse_list( $list );
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value );
}
return array_unique( $list );
return array_unique( array_map( 'sanitize_title', $list ) );
}
/**

View File

@ -5088,7 +5088,7 @@ function get_pages( $args = array() ) {
$author_query = '';
if ( ! empty( $r['authors'] ) ) {
$post_authors = preg_split( '/[\s,]+/', $r['authors'] );
$post_authors = wp_parse_list( $r['authors'] );
if ( ! empty( $post_authors ) ) {
foreach ( $post_authors as $post_author ) {

View File

@ -679,7 +679,7 @@ function rest_filter_response_fields( $response, $server, $request ) {
$data = $response->get_data();
$fields = is_array( $request['_fields'] ) ? $request['_fields'] : preg_split( '/[\s,]+/', $request['_fields'] );
$fields = wp_parse_list( $request['_fields'] );
if ( 0 === count( $fields ) ) {
return $response;
@ -1109,8 +1109,8 @@ function rest_get_avatar_sizes() {
*/
function rest_validate_value_from_schema( $value, $args, $param = '' ) {
if ( 'array' === $args['type'] ) {
if ( ! is_array( $value ) ) {
$value = preg_split( '/[\s,]+/', $value );
if ( ! is_null( $value ) ) {
$value = wp_parse_list( $value );
}
if ( ! wp_is_numeric_array( $value ) ) {
/* translators: 1: parameter, 2: type name */
@ -1253,9 +1253,7 @@ function rest_sanitize_value_from_schema( $value, $args ) {
if ( empty( $args['items'] ) ) {
return (array) $value;
}
if ( ! is_array( $value ) ) {
$value = preg_split( '/[\s,]+/', $value );
}
$value = wp_parse_list( $value );
foreach ( $value as $index => $v ) {
$value[ $index ] = rest_sanitize_value_from_schema( $v, $args['items'] );
}

View File

@ -532,7 +532,7 @@ abstract class WP_REST_Controller {
if ( ! isset( $request['_fields'] ) ) {
return $fields;
}
$requested_fields = is_array( $request['_fields'] ) ? $request['_fields'] : preg_split( '/[\s,]+/', $request['_fields'] );
$requested_fields = wp_parse_list( $request['_fields'] );
if ( 0 === count( $requested_fields ) ) {
return $fields;
}

View File

@ -13,7 +13,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.1-alpha-44545';
$wp_version = '5.1-alpha-44546';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.