From 14f599ea7def7c7a59c40aff763ce8b105573e7a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 31 Aug 2021 10:46:22 +0200 Subject: [PATCH] Use zend_long for resource ID Currently, resource IDs are limited to 32-bits. As resource IDs are not reused, this means that resource ID overflow for long-running processes is very possible. This patch switches resource IDs to use zend_long instead, which means that on 64-bit systems, 64-bit resource IDs will be used. This makes resource ID overflow practically impossible. The tradeoff is an 8 byte increase in zend_resource size. Closes GH-7436. --- UPGRADING.INTERNALS | 4 ++++ Zend/zend_execute.c | 4 +++- Zend/zend_list.c | 5 ++--- Zend/zend_types.h | 2 +- ext/oci8/oci8.c | 2 +- ext/standard/file.c | 2 +- ext/standard/var.c | 4 ++-- sapi/phpdbg/phpdbg_utils.c | 2 +- 8 files changed, 15 insertions(+), 10 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index e5c78b2d6e4..ec4d17f20ac 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -9,6 +9,7 @@ PHP 8.1 INTERNALS UPGRADE NOTES f. Non-serializable classes should use ZEND_ACC_NOT_SERIALIZABLE g. _zend_hash_find_known_hash renamed to zend_hash_find_known_hash h. Renaming of ZEND_TYPE_HAS_CLASS() into ZEND_TYPE_IS_COMPLEX() + i. zend_resource handle is now zend_long 2. Build system changes a. New compiler flags @@ -58,6 +59,9 @@ PHP 8.1 INTERNALS UPGRADE NOTES h. ZEND_TYPE_HAS_CLASS() has been renamed to ZEND_TYPE_IS_COMPLEX() for clarity. A zend_type element can contain a zend_type_list which might be either a union or an intersection, or a single class stored as either a zend_string* or a zend_class_entry*. + i. The handle member of zend_resource (the resource ID) now has type zend_long + rather than int. This should be transparent to most code, but uses in + printf may need to switch from "%d" to ZEND_LONG_FMT. ======================== 2. Build system changes diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c1cde8af1b8..be25d947493 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2166,7 +2166,9 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(vo ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim) { - zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); + zend_error(E_WARNING, + "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (" ZEND_LONG_FMT ")", + Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_string(void) diff --git a/Zend/zend_list.c b/Zend/zend_list.c index 5cc449594ff..b3409e33ce8 100644 --- a/Zend/zend_list.c +++ b/Zend/zend_list.c @@ -31,13 +31,12 @@ static HashTable list_destructors; ZEND_API zval* ZEND_FASTCALL zend_list_insert(void *ptr, int type) { - int index; zval zv; - index = zend_hash_next_free_element(&EG(regular_list)); + zend_long index = zend_hash_next_free_element(&EG(regular_list)); if (index == 0) { index = 1; - } else if (index == INT_MAX) { + } else if (index == ZEND_LONG_MAX) { zend_error_noreturn(E_ERROR, "Resource ID space overflow"); } ZVAL_NEW_RES(&zv, index, ptr, type); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index dd55e733aeb..fe551c38820 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -485,7 +485,7 @@ struct _zend_object { struct _zend_resource { zend_refcounted_h gc; - int handle; // TODO: may be removed ??? + zend_long handle; // TODO: may be removed ??? int type; void *ptr; }; diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 891d4322bb0..1f8a5833fcd 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -1711,7 +1711,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode) descriptor = (php_oci_descriptor *) column->descid->ptr; if (!descriptor) { - php_error_docref(NULL, E_WARNING, "Unable to find LOB descriptor #%d", column->descid->handle); + php_error_docref(NULL, E_WARNING, "Unable to find LOB descriptor #" ZEND_LONG_FMT, column->descid->handle); return 1; } diff --git a/ext/standard/file.c b/ext/standard/file.c index bc33740d0ff..0c1d03fdc85 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -908,7 +908,7 @@ PHPAPI PHP_FUNCTION(fclose) PHP_STREAM_TO_ZVAL(stream, res); if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) { - php_error_docref(NULL, E_WARNING, "%d is not a valid stream resource", stream->res->handle); + php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " is not a valid stream resource", stream->res->handle); RETURN_FALSE; } diff --git a/ext/standard/var.c b/ext/standard/var.c index 74fcc9c7a8c..ef4b019fb6e 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -195,7 +195,7 @@ again: } case IS_RESOURCE: { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc)); - php_printf("%sresource(%d) of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown"); + php_printf("%sresource(" ZEND_LONG_FMT ") of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown"); break; } case IS_REFERENCE: @@ -380,7 +380,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ break; case IS_RESOURCE: { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc)); - php_printf("resource(%d) of type (%s) refcount(%u)\n", Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc)); + php_printf("resource(" ZEND_LONG_FMT ") of type (%s) refcount(%u)\n", Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc)); break; } case IS_REFERENCE: diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 0e46936fc62..344b9c73e47 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -702,7 +702,7 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */ zend_string_release(str); } break; case IS_RESOURCE: - spprintf(&decode, 0, "Rsrc #%d", Z_RES_HANDLE_P(zv)); + spprintf(&decode, 0, "Rsrc #" ZEND_LONG_FMT, Z_RES_HANDLE_P(zv)); break; case IS_ARRAY: spprintf(&decode, 0, "array(%d)", zend_hash_num_elements(Z_ARR_P(zv)));