Repository navigation
Database: Unescape prepared LIKE operands in wpdb::get_table_from_query() - #14889
bluefairydevelopment wants to merge 2 commits into
Conversation
…ry(). A SHOW TABLES LIKE query built with wpdb::prepare() and wpdb::esc_like() has its backslashes escaped once more as a string literal, so the table name came back as wp\_my\_table. Remove the string literal escaping before unescaping the underscores. See #57149.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @bluefairydevelopment. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
JJJ
left a comment
There was a problem hiding this comment.
The exact-name fix looks correct for the reported esc_like() plus prepare() case, and the existing single-escaped cases retain their behavior. One wording adjustment would help future reviews: the description says this and 57149.2.diff produce the same result for every name accepted by the parser, but the parser also accepts backslashes and this patch collapses doubled backslashes outside \\_. The documented limitation for table names containing backslashes is reasonable for this ticket; please qualify that equivalence claim to names without backslashes.
| return array( | ||
| 'SHOW TABLES, single quotes' => array( "SHOW TABLES LIKE 'wp\\\\_my\\\\_custom\\\\_table'", 'wp_my_custom_table' ), | ||
| 'SHOW TABLES, double quotes' => array( 'SHOW TABLES LIKE "wp\\\\_my\\\\_custom\\\\_table"', 'wp_my_custom_table' ), | ||
| 'SHOW TABLE STATUS, prefix wildcard' => array( "SHOW TABLE STATUS LIKE 'wp\\\\_123\\\\_%'", 'wp_123_' ), |
There was a problem hiding this comment.
This covers the trailing wildcard with a handwritten SQL string. The routing path builds the operand with esc_like( $prefix ) . '%' and prepare(), which temporarily replaces % with a placeholder token until the query filter removes it. Please add a case that prepares the wildcard query and runs it through that filter (or remove_placeholder_escape()) before asserting the extracted prefix. That will verify the escape and filter order used by database drop-ins.
…ape is removed. Builds the wildcard operand with esc_like() and prepare(), then removes the placeholder escape as the query filter does, before checking the prefix that get_table_from_query() returns.
|
Thanks, both done.
|
wpdb::get_table_from_query()unescapes\_in aSHOW TABLES LIKEoperand. A query built the documented way,$wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ), is escaped twice:esc_like()turns_into\_, thenprepare()escapes the backslash again as a string literal, giving'wp\\_my\\_custom\\_table'. Trunk only undoes the first step, so the table name comes back aswp\_my\_custom\_table. That breaks drop-ins such as HyperDB, LudicrousDB and BerlinDB, which route queries by table name.This removes the string-literal escaping (
\\→\) before unescaping the underscores (\_→_). Hand-written operands such as'wp\_123\_%'contain no doubled backslashes and behave exactly as before; the existingdata_get_escaped_table_from_show_querycases still pass. This builds on the reporter prettyboymp's patch on Trac (57149.2.diff), which replaces both\\_and\_with_in one step. Both versions pass the same tests and give the same results for every table name without a backslash that the parsing pattern accepts. With backslashes they can differ, because this patch also collapses doubled backslashes that are not followed by an underscore (see "Not covered" below). This one undoes the two escaping layers in reverse order, so it doesn't depend on the backslash sitting directly before an underscore, and it adds the unit tests the ticket was missing.Not covered: backslashes inside table names. As johnjamesjacoby noted in comment:1, MySQL allows
\in a table name, and neither trunk nor this change handles that: a name containing a literal backslash would still be mis-parsed. WordPress never creates such tables, and handling them properly would mean deciding howSHOW ... LIKEqueries should be escaped across core, which is the open question in that comment. This PR keeps to the documentedprepare()+esc_like()pattern, which core itself uses inmaybe_create_table(),network_domain_check()and elsewhere.Tests
test_get_table_from_prepared_show_like_query, coveringSHOW TABLES,SHOW TABLE STATUSandSHOW FULL TABLESwith both quote styles and a trailing wildcard, plustest_get_table_from_query_built_with_prepare_and_esc_like, which builds the query with the realprepare()andesc_like().test_get_table_from_query_built_with_prepare_esc_like_and_wildcardprepares a prefix pattern with a trailing%and removes the placeholder escape, as thequeryfilter does, before looking up the table.wp\_my\_custom\_table/wp\_123\_.--group wpdbpasses (666 tests, 0 failures, 0 errors) on PHP 8.5 / MariaDB 10.11; phpcs clean.Trac ticket: https://core.trac.wordpress.org/ticket/57149
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: reading the ticket and the code, the fix, and the tests, including confirming that the tests fail without the fix and pass with it. Submitted by Blue Fairy Development, who are responsible for the change.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.