#35493 closed defect (bug) (fixed)
get_terms does not return correct value when a term is searched by a name containing a single quote
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 4.5 | Priority: | normal |
Severity: | normal | Version: | 4.3 |
Component: | Taxonomy | Keywords: | |
Focuses: | Cc: |
Description
get_terms() function does not return correct value when a term is searched by a name containing a single quote ('). Apparently the terms name get escaped twice.
To reproduce it, first add one tag with name containing ', like Chef d'oeuvre, then use this function:
$name = "Chef d'oeuvre"; $terms = get_terms('post_tag', array( 'name' => $name, 'hide_empty' => false )); var_dump($terms); // array(0) { }
I think the problem lies in /wp-includes/taxonomy.php, lines 1296-1301 (https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/taxonomy.php#L1296):
$names = (array) $args['name']; var_dump($names); // array(1) { [0]=> string(13) "Chef d'oeuvre" } foreach ( $names as &$_name ) { $_name = sanitize_term_field( 'name', $_name, 0, reset( $taxonomies ), 'db' ); } var_dump($names); // array(1) { [0]=> &string(14) "Chef d\'oeuvre" } $where .= " AND t.name IN ('" . implode( "', '", array_map( 'esc_sql', $names ) ) . "')"; var_dump($where ); // "tt.taxonomy IN ('post_tag') AND t.name IN ('Chef d\\\'oeuvre')"
I'd suggest to just remove the last esc_sql formatting, but I am not sure if it may lead to other problems.
Change History (3)
Note: See
TracTickets for help on using
tickets.
@maximeschoeni Welcome to WordPress Trac! Thanks for the detailed report.
I've confirmed the issue, and traced it to [32353]. In that changeset, we switched from sanitizing using
sanitize_text_field()
on the value ofname
to usingsanitize_term_field( 'name' )
. This change was necessary because terms go through thesanitize_term_field()
filter when being saved in the first place, so that terms names are run through a couple different sanitization routines before being stored in the database.One thing that
sanitize_term_field( 'name' )
does is run the$name
throughwp_filter_kses()
. This function runsstripslashes()
on the value passed to it, and then runsaddslashes()
to it again before returning it. This is becausewp_filter_kses()
expects slashed data. Butget_terms()
expects the 'name' param to be unslashed already; see egWP_Terms_List_Table::prepare_items()
, where the search term is unslashed before being passed toget_terms()
.Technically, the
addslashes()
performed bywp_filter_kses()
does the same thing as the call toesc_sql()
that you've pointed out. But this is partially an accident of howwp_filter_kses()
- a function that was not designed for MySQL escaping - was designed. So, for developer clarity, it's probably wiser to keep the lateesc_sql()
escaping as-is but remove slashes on what's returned fromsanitize_term_field()
.