From df1bf4a883248e5bbfd024e883ca0dabe11bb7d2 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 18 Sep 2017 23:03:06 +0000 Subject: [PATCH] Customize: Add `wp_is_uuid()` validation function with optional second `$version=4` parameter to enforce v4 random UUIDs. Props jonathanbardo. Fixes #39778. git-svn-id: https://develop.svn.wordpress.org/trunk@41388 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-customize-manager.php | 2 +- src/wp-includes/functions.php | 28 ++++++++++ tests/phpunit/tests/functions.php | 52 ++++++++++++++++++- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-customize-manager.php b/src/wp-includes/class-wp-customize-manager.php index cead2d0ce9..7bd1489543 100644 --- a/src/wp-includes/class-wp-customize-manager.php +++ b/src/wp-includes/class-wp-customize-manager.php @@ -488,7 +488,7 @@ final class WP_Customize_Manager { return; } - if ( ! preg_match( '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', $this->_changeset_uuid ) ) { + if ( ! wp_is_uuid( $this->_changeset_uuid ) ) { $this->wp_die( -1, __( 'Invalid changeset UUID' ) ); } diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index bab1f7463b..2559613fbc 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -5704,6 +5704,34 @@ function wp_generate_uuid4() { ); } +/** + * Validates that a UUID is valid. + * + * @since 4.9.0 + * + * @param mixed $uuid UUID to check. + * @param int $version Specify which version of UUID to check against. Default is none, to accept any UUID version. Otherwise, only version allowed is `4`. + * @return bool The string is a valid UUID or false on failure. + */ +function wp_is_uuid( $uuid, $version = null ) { + + if ( ! is_string( $uuid ) ) { + return false; + } + + if ( is_numeric( $version ) ) { + if ( 4 !== (int) $version ) { + _doing_it_wrong( __FUNCTION__, __( 'Only UUID V4 is supported at this time.' ), '4.9.0' ); + return false; + } + $regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/'; + } else { + $regex = '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/'; + } + + return (bool) preg_match( $regex, $uuid ); +} + /** * Get last changed date for the specified cache group. * diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 252d890bbb..3fa9fbcc74 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -901,7 +901,7 @@ class Tests_Functions extends WP_UnitTestCase { $uuids = array(); for ( $i = 0; $i < 20; $i += 1 ) { $uuid = wp_generate_uuid4(); - $this->assertRegExp( '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid ); + $this->assertTrue( wp_is_uuid( $uuid, 4 ) ); $uuids[] = $uuid; } @@ -909,6 +909,56 @@ class Tests_Functions extends WP_UnitTestCase { $this->assertEquals( $uuids, $unique_uuids ); } + /** + * Tests wp_is_uuid(). + * + * @covers ::wp_is_uuid + * @ticket 39778 + */ + function test_wp_is_valid_uuid() { + $uuids_v4 = array( + '27fe2421-780c-44c5-b39b-fff753092b55', + 'b7c7713a-4ee9-45a1-87ed-944a90390fc7', + 'fbedbe35-7bf5-49cc-a5ac-0343bd94360a', + '4c58e67e-123b-4290-a41c-5eeb6970fa3e', + 'f54f5b78-e414-4637-84a9-a6cdc94a1beb', + 'd1c533ac-abcf-44b6-9b0e-6477d2c91b09', + '7fcd683f-e5fd-454a-a8b9-ed15068830da', + '7962c750-e58c-470a-af0d-ec1eae453ff2', + 'a59878ce-9a67-4493-8ca0-a756b52804b3', + '6faa519d-1e13-4415-bd6f-905ae3689d1d', + ); + + foreach ( $uuids_v4 as $uuid ) { + $this->assertTrue( wp_is_uuid( $uuid, 4 ) ); + } + + $uuids = array( + '00000000-0000-0000-0000-000000000000', // Nil. + '9e3a0460-d72d-11e4-a631-c8e0eb141dab', // Version 1. + '2c1d43b8-e6d7-376e-af7f-d4bde997cc3f', // Version 3. + '39888f87-fb62-5988-a425-b2ea63f5b81e', // Version 5. + ); + + foreach ( $uuids as $uuid ) { + $this->assertTrue( wp_is_uuid( $uuid ) ); + $this->assertFalse( wp_is_uuid( $uuid, 4 ) ); + } + + $invalid_uuids = array( + 'a19d5192-ea41-41e6-b006', + 'this-is-not-valid', + 1234, + true, + array(), + ); + + foreach ( $invalid_uuids as $invalid_uuid ) { + $this->assertFalse( wp_is_uuid( $invalid_uuid, 4 ) ); + $this->assertFalse( wp_is_uuid( $invalid_uuid ) ); + } + } + /** * @ticket 40017 * @dataProvider _wp_get_image_mime