[wp-trac] [WordPress Trac] #38203: Remove `absint` on object IDs in `delete_metadata`, etc
WordPress Trac
noreply at wordpress.org
Wed Apr 12 00:46:47 UTC 2017
#38203: Remove `absint` on object IDs in `delete_metadata`, etc
--------------------------------+------------------------------
Reporter: peterwilsoncc | Owner:
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Options, Meta APIs | Version: 2.9
Severity: normal | Resolution:
Keywords: 2nd-opinion | Focuses:
--------------------------------+------------------------------
Changes (by johnjamesjacoby):
* keywords: has-patch commit => 2nd-opinion
Comment:
**Research**
I put a few hours of investigation into this today. It's really hard not
to do a deeper dive into all `absint()` and `intval()` usages everywhere,
because numeric values get changed in so many places.
Looking at the numerous usages of both functions, it seems at first like a
flawed design, but there's actually a lot more going on that makes this
surprisingly tricky to explain.
As was stated in the ticket description, the 2 problems are:
* `absint()` will turn negative numbers into their positive (absolute)
equivalent
* `intval()` will not change floats (really large numbers, beyond
`PHP_INT_MAX` and `PHP_INT_MIN`) and those constants have different values
based on system configuration (32/64 bit, etc...)
----
**Case 1**
The following code will save to post ID `1` and not `-1`, thanks to
`absint()`:
{{{
update_post_meta( -1, 'foo', 'bar' );
}}}
** Case 2 **
Imagine that `PHP_INT_MAX` has a value of `9223372036854775807`, which is
pretty standard:
{{{
$id_max = 9223372036854775807;
$id_max_one = $id_max + 1;
}}}
And we want to use them directly:
{{{
var_dump( $id_max );
var_dump( $id_max_one );
}}}
Will result in:
{{{
int 9223372036854775807
float 9.2233720368548E+18
}}}
Once we cast them as `int`s, weird stuff starts happening:
{{{
var_dump( (int) $id_max );
var_dump( (int) $id_max_one );
}}}
The float comes out as flipped into the minimum negative integer:
{{{
int 9223372036854775807
int -9223372036854775808
}}}
What we've learned here is that `(int)` or `intval()` alone are not enough
to always get a trustworthy ID value.
----
**Discovery**
Most of the `ID` type columns (for posts/comments/users/terms) in
WordPress are `BIGINT(20)` (and that does not mean what I think most
people would feel safe assuming it means, which is some number up to 20
digits in length. That is not the case. The `20` is simply a display hint,
usually for padding zeroes.)
[https://dev.mysql.com/doc/refman/5.7/en/integer-types.html
Minimum/Maximum values] are dependent on whether the column is signed or
unsigned, and while WordPress single-site database tables were normalized
in #8751, it's multisite tables all remain `signed` when they should be
`unsigned`. The most likely reason for this is `signed` is assumed if
`unsigned` is not explicitly passed, and way back when those tables were
new, the single-site tables were still "in a way" as my wife likes to say.
----
**Conclusion**
Knowing that post/comment/user/term `ID` columns are `unsigned`, I believe
`absint()` is the correct call to make here, because the database simply
cannot store negative numbers in `BIGINT(20) unsigned` columns.
This means my comment above on being able to store `-1` in the
`wp_sitemeta:site_id` column, is unintended behavior, and should be
changed.
**To-do's**
* Educate community about why negative numbers are not allowed for object
IDs
* A new ticket should be opened to update `$ms_global_tables` database
tables to alter the relevant `signed` columns into `unsigned` columns.
This may involve an upgrade routine, which needs to obey
`wp_should_upgrade_global_tables()`.
* Awareness campaign about breaking changes to multisite global tables, in
the very off chance someone is storing negative values where they can no
longer exist.
* Educate multisite plugin developers about the above breaking changes
* Close this ticket as a wontfix
* BONUS: Many plugins with custom database tables do not use `unsigned`
integers, including BuddyPress, WooCommerce, EDD, and more. They should
all be updated at their earliest convenience as well.
----
With all of that said, I'd like to make a motion to close this ticket as
wontfix.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/38203#comment:5>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list