[wp-trac] [WordPress Trac] #57149: get_table_from_query() doesn't properly handle a prepared escape_like() table name
WordPress Trac
noreply at wordpress.org
Sun Nov 20 22:52:00 UTC 2022
#57149: get_table_from_query() doesn't properly handle a prepared escape_like()
table name
--------------------------+------------------------------
Reporter: prettyboymp | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Database | Version:
Severity: normal | Resolution:
Keywords: | Focuses: multisite
--------------------------+------------------------------
Comment (by johnjamesjacoby):
Hey @prettyboymp 👋 nice find 🔍 nice patch 🙌
I am able to reproduce this defect in:
* Vanilla WordPress wpdb
* `maybe_create_table()` (not the one in `install-helper.php`)
* `network_domain_check()`
* `display_setup_form()`
* `wp-admin/maint/repair.php`
* HyperDB
* LudicrousDB
* BerlinDB
Your suggested code change does successfully resolve the problem as you've
reported it 💎
----
Additional research & testing has revealed some potential tangential
defects 😬
1. `\` is a ''legal'' character in MySQL table names:
{{{
CREATE TABLE `wp\_users` LIKE `wp_users`;
CREATE TABLE `wp\\_users` LIKE `wp\_users`;
CREATE TABLE `wp\\\_users` LIKE `wp\\_users`;
CREATE TABLE `wp\\\\_users` LIKE `wp\\\_users`;
CREATE TABLE `wp\_\_\_users` LIKE `wp\\\\_users`;
CREATE TABLE `wp\_\_\_\_users` LIKE `wp\\\\_users`;
SHOW TABLES LIKE 'wp%users';
}}}
1. WordPress does not list `NO_BACKSLASH_ESCAPES` as an incompatible mode
in `wpdb`– #3286
1. WordPress does not use the `ESCAPE` clause to enforce `\` as the escape
character
1. Documentation for
[https://developer.wordpress.org/reference%2Fclasses%2Fwpdb%2Fprepare%2F/
wpdb::prepare()] includes the following:
{{{
Literal percentage signs (`%`) in the query string must be written as
`%%`. Percentage wildcards
(for example, to use in LIKE syntax) must be passed via a substitution
argument containing
the complete LIKE string, these cannot be inserted directly in the query
string.
Also see wpdb::esc_like().
}}}
Interpretation:
1. Emphasis: **Percentage wildcards** (to use in LIKE syntax) must be
passed via a substitution argument containing the complete LIKE string,
these cannot be inserted directly in the query string.
1. Missing: The docs ''do not'' instruct to use a similar approach for
**Underscore wildcards**, or really what approach to use for them at all.
----
Conclusions:
1. Table names & Columns in `SHOW ... LIKE %s` queries
* ''most likely'' should not use `$wpdb->esc_like()`
* ''most likely'' should not use `$wpdb->prepare()`
1. Otherwise, they are mangled with unnecessary slashes
* ...causing subsequent `$wpdb->get_var()` queries to fail...
* ...because a table name like `wp_users` gets:
* esc_like'ed to `wp\_users`
* prepare'ed to `wp\\_users`
* even though:
* `wp_users` is adequately "wild"
* `wp\_users` is not syntactically what was being queried
* `wp\\_users` is not syntactically what was being queried
* and `_` does not need escaping the way `%` does
* I.E. `\_\_\_` needs to mean `wp\_\_\_users` and cannot mean
`wp___users`
1. Instead, ''most likely'', these queries should be concatenated,
unescaped and unprepared, and manually slashed to accommodate the desired
matching:
{{{
$like = 'wp\\\_\\\_\\\_\\\_users';
$sql = 'SHOW TABLES LIKE ' . $like;
$query = $wpdb->get_var( $sql );
}}}
In this way, the core `str_replace( '\\_', '_', $maybe[2] )` is
surprisingly accurate.
1. Perhaps, we are all doing it wrong everywhere, and a deeper
conclusion is required? (Additionally plausible is that I've missed a
mundane detail and all of this is wrong 🌚)
--
Ticket URL: <https://core.trac.wordpress.org/ticket/57149#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list