From 665379865f43ea5dfef526c2dcc197c78ad5d1f5 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 22 Jun 2017 23:18:47 -0700 Subject: [PATCH 1/4] Implement a POC for spl_object_id(object $x) : int https://github.com/runkit7/runkit_object_id is a C module which implements the same functionality (Without obfuscation) Pending question: Can `sizeof(zend_long)` be > `sizeof(intptr_t)` - If so, detect that condition at compile time and return a binary string with that many bytes, instead. Also, can two PHP "object"s have the same object id, but different object handlers? (E.g. iterator of a class) - If that is so, then document if this case is possible, but keep behaving the same way. --- ext/spl/php_spl.c | 43 ++++++++++++++++++++++++++++++++++++++++--- ext/spl/php_spl.h | 1 + 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 34b54e81e1ddb..2ee02d3bbecce 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -794,14 +794,32 @@ PHP_FUNCTION(spl_object_hash) } /* }}} */ +/* {{{ proto int spl_object_id(object obj) + Return integer hash id for given object */ +PHP_FUNCTION(spl_object_id) +{ + zval *obj; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJECT(obj) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_NULL()); + + RETURN_LONG(php_spl_object_id(obj)); +} +/* }}} */ + +static void php_spl_init_hash_mask() { + SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand() >> 1); + SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1); + SPL_G(hash_mask_init) = 1; +} + PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ { intptr_t hash_handle, hash_handlers; if (!SPL_G(hash_mask_init)) { - SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand() >> 1); - SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1); - SPL_G(hash_mask_init) = 1; + php_spl_init_hash_mask(); } hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); @@ -811,6 +829,20 @@ PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ } /* }}} */ +PHPAPI zend_long php_spl_object_id(zval *obj) /* {{{*/ +{ + intptr_t hash_handle; + + if (!SPL_G(hash_mask_init)) { + php_spl_init_hash_mask(); + } + + hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); + + return (zend_long) hash_handle; +} +/* }}} */ + int spl_build_class_list_string(zval *entry, char **list) /* {{{ */ { char *res; @@ -915,6 +947,10 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_object_hash, 0, 0, 1) ZEND_ARG_INFO(0, obj) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_object_id, 0, 0, 1) + ZEND_ARG_INFO(0, obj) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ spl_functions @@ -931,6 +967,7 @@ const zend_function_entry spl_functions[] = { PHP_FE(class_implements, arginfo_class_implements) PHP_FE(class_uses, arginfo_class_uses) PHP_FE(spl_object_hash, arginfo_spl_object_hash) + PHP_FE(spl_object_id, arginfo_spl_object_id) #ifdef SPL_ITERATORS_H PHP_FE(iterator_to_array, arginfo_iterator_to_array) PHP_FE(iterator_count, arginfo_iterator) diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h index 23e4f539be00b..0efc56553a01a 100644 --- a/ext/spl/php_spl.h +++ b/ext/spl/php_spl.h @@ -71,6 +71,7 @@ PHP_FUNCTION(class_implements); PHP_FUNCTION(class_uses); PHPAPI zend_string *php_spl_object_hash(zval *obj); +PHPAPI zend_long php_spl_object_id(zval *obj); #endif /* PHP_SPL_H */ From 92c1158242ce104fd9dc0d9cda67659bee4dc8b6 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 5 Jul 2017 21:45:41 -0700 Subject: [PATCH 2/4] Address review comments. Remove pointless XORing. Don't move this into a utility function, it would be the same as `(zend_long)Z_OBJ_HANDLE_P(obj)` --- ext/spl/php_spl.c | 26 ++++---------------------- ext/spl/php_spl.h | 1 - 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 2ee02d3bbecce..5f2d4cfe291f2 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -804,22 +804,18 @@ PHP_FUNCTION(spl_object_id) Z_PARAM_OBJECT(obj) ZEND_PARSE_PARAMETERS_END_EX(RETURN_NULL()); - RETURN_LONG(php_spl_object_id(obj)); + RETURN_LONG((zend_long)Z_OBJ_HANDLE_P(obj)); } /* }}} */ -static void php_spl_init_hash_mask() { - SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand() >> 1); - SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1); - SPL_G(hash_mask_init) = 1; -} - PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ { intptr_t hash_handle, hash_handlers; if (!SPL_G(hash_mask_init)) { - php_spl_init_hash_mask(); + SPL_G(hash_mask_handle) = (intptr_t)(php_mt_rand() >> 1); + SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1); + SPL_G(hash_mask_init) = 1; } hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); @@ -829,20 +825,6 @@ PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ } /* }}} */ -PHPAPI zend_long php_spl_object_id(zval *obj) /* {{{*/ -{ - intptr_t hash_handle; - - if (!SPL_G(hash_mask_init)) { - php_spl_init_hash_mask(); - } - - hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); - - return (zend_long) hash_handle; -} -/* }}} */ - int spl_build_class_list_string(zval *entry, char **list) /* {{{ */ { char *res; diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h index 0efc56553a01a..23e4f539be00b 100644 --- a/ext/spl/php_spl.h +++ b/ext/spl/php_spl.h @@ -71,7 +71,6 @@ PHP_FUNCTION(class_implements); PHP_FUNCTION(class_uses); PHPAPI zend_string *php_spl_object_hash(zval *obj); -PHPAPI zend_long php_spl_object_id(zval *obj); #endif /* PHP_SPL_H */ From 74bd4f016f11c8bb8c96ed372efe4f7d8c02b149 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 5 Jul 2017 21:50:22 -0700 Subject: [PATCH 3/4] Commit unit test of spl_object_id --- ext/spl/tests/spl_object_id.phpt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 ext/spl/tests/spl_object_id.phpt diff --git a/ext/spl/tests/spl_object_id.phpt b/ext/spl/tests/spl_object_id.phpt new file mode 100644 index 0000000000000..e316bd01f93fc --- /dev/null +++ b/ext/spl/tests/spl_object_id.phpt @@ -0,0 +1,24 @@ +--TEST-- +SPL: spl_object_id() +--FILE-- + +===DONE=== + +--EXPECTF-- +int(%d) + +Warning: spl_object_id() expects parameter 1 to be object, integer given in %sspl_object_id.php on line %d +NULL + +Warning: spl_object_id() expects exactly 1 parameter, 0 given in %sspl_object_id.php on line %d +NULL +bool(false) +===DONE=== From 6bc274582c8c5a90b18f498be24d217075c3c7cf Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Wed, 5 Jul 2017 22:05:37 -0700 Subject: [PATCH 4/4] Update NEWS --- NEWS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d3604ee6eb2c1..2e0d76c5e9cf4 100644 --- a/NEWS +++ b/NEWS @@ -28,9 +28,11 @@ PHP NEWS (Anatol) - SPL: + . Added spl_object_id() function returning an integer (the object handle) for an object. + (Tyson Andre) . Fixed bug #73471 (PHP freezes with AppendIterator). (jhdxr) . Fixed bug #71412 (Incorrect arginfo for ArrayIterator::__construct). - (tysonandre775 at hotmail dot com) + (Tyson Andre) - Session: . Fixed bug #74514 (5 session functions incorrectly warn when calling in