From 71c5eb77cde99a9b661bb6dcf89223b59c4d6023 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:36:17 +0200 Subject: [PATCH 01/12] Use int64 for zend_long --- Zend/Zend.m4 | 38 +++++++++++++++++++++++++++++++++++++ Zend/zend_alloc.c | 30 ++++++++++++++--------------- Zend/zend_compile.c | 2 +- Zend/zend_execute.c | 12 ++++++------ Zend/zend_execute_API.c | 2 +- Zend/zend_generators.c | 6 +++--- Zend/zend_inheritance.c | 4 ++-- Zend/zend_long.h | 10 +++++++++- Zend/zend_object_handlers.c | 2 +- Zend/zend_operators.h | 8 ++++---- Zend/zend_range_check.h | 23 ++++++++++++++++++---- Zend/zend_string.c | 5 ++--- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 10 +++++----- Zend/zend_vm_execute.skl | 6 +++--- Zend/zend_vm_trace_map.h | 2 +- Zend/zend_weakrefs.c | 10 +++++----- 17 files changed, 116 insertions(+), 56 deletions(-) diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 41da8344bf1f..9e280c200915 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -212,6 +212,7 @@ AX_CHECK_COMPILE_FLAG([-fno-common], [CFLAGS="-fno-common $CFLAGS"]) ZEND_CHECK_ALIGNMENT +ZEND_CHECK_INT64 ZEND_CHECK_SIGNALS ZEND_CHECK_MAX_EXECUTION_TIMERS ]) @@ -416,6 +417,43 @@ AS_VAR_IF([php_cv_align_mm], [failed], ]) ]) +dnl +dnl ZEND_CHECK_INT64 +dnl +dnl Check whether to enable 64 bit integer if supported by the system. +dnl +AC_DEFUN([ZEND_CHECK_INT64], [dnl + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[]], + [[ + #if !(defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) + #error "Not a 64-bit platform" + #endif + ]] + )], + [ZEND_INT64=yes], + [ZEND_INT64=no]) + + AC_ARG_ENABLE([zend-int64], + [AS_HELP_STRING([--enable-zend-int64], [Enable 64bit integer support (enabled by default on 64bit arch)])], + [ZEND_INT64=$enableval], + [ZEND_INT64=$ZEND_INT64]) + + AS_VAR_IF([ZEND_INT64], [yes], + AC_CHECK_TYPE([int64_t],, + [AC_MSG_ERROR([int64_t not found])], + [#include ])) + + AS_VAR_IF([ZEND_INT64], [yes], + [AC_DEFINE([ZEND_INT64], [1], + [Define to 1 if zend_long as int64 is supported and enabled.]) + AS_VAR_APPEND([CFLAGS], [" -DZEND_INT64"])]) + + AC_MSG_CHECKING([whether to enable 64 bit integer support]) + AC_MSG_RESULT([$ZEND_INT64]) +]) + dnl dnl ZEND_CHECK_SIGNALS dnl diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index f6c0a1ad0e98..e0dd60d99e58 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -173,7 +173,7 @@ static size_t _real_page_size = ZEND_MM_PAGE_SIZE; #endif typedef uint32_t zend_mm_page_info; /* 4-byte integer */ -typedef zend_ulong zend_mm_bitset; /* 4-byte or 8-byte integer */ +typedef size_t zend_mm_bitset; /* 4-byte or 8-byte integer */ #define ZEND_MM_ALIGNED_OFFSET(size, alignment) \ (((size_t)(size)) & ((alignment) - 1)) @@ -571,7 +571,7 @@ static void *zend_mm_mmap(size_t size) /* number of trailing set (1) bits */ ZEND_ATTRIBUTE_CONST static zend_always_inline int zend_mm_bitset_nts(zend_mm_bitset bitset) { -#if (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) && SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CTZL) +#if (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) && SIZEOF_SIZE_T == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CTZL) return __builtin_ctzl(~bitset); #elif (defined(__GNUC__) || __has_builtin(__builtin_ctzll)) && defined(PHP_HAVE_BUILTIN_CTZLL) return __builtin_ctzll(~bitset); @@ -594,7 +594,7 @@ ZEND_ATTRIBUTE_CONST static zend_always_inline int zend_mm_bitset_nts(zend_mm_bi if (bitset == (zend_mm_bitset)-1) return ZEND_MM_BITSET_LEN; n = 0; -#if SIZEOF_ZEND_LONG == 8 +#if SIZEOF_SIZE_T == 8 if (sizeof(zend_mm_bitset) == 8) { if ((bitset & 0xffffffff) == 0xffffffff) {n += 32; bitset = bitset >> Z_UL(32);} } @@ -614,12 +614,12 @@ static zend_always_inline int zend_mm_bitset_is_set(zend_mm_bitset *bitset, int static zend_always_inline void zend_mm_bitset_set_bit(zend_mm_bitset *bitset, int bit) { - bitset[bit / ZEND_MM_BITSET_LEN] |= (Z_UL(1) << (bit & (ZEND_MM_BITSET_LEN-1))); + bitset[bit / ZEND_MM_BITSET_LEN] |= ((zend_mm_bitset)1 << (bit & (ZEND_MM_BITSET_LEN-1))); } static zend_always_inline void zend_mm_bitset_reset_bit(zend_mm_bitset *bitset, int bit) { - bitset[bit / ZEND_MM_BITSET_LEN] &= ~(Z_UL(1) << (bit & (ZEND_MM_BITSET_LEN-1))); + bitset[bit / ZEND_MM_BITSET_LEN] &= ~((zend_mm_bitset)1 << (bit & (ZEND_MM_BITSET_LEN-1))); } static zend_always_inline void zend_mm_bitset_set_range(zend_mm_bitset *bitset, int start, int len) @@ -2174,7 +2174,7 @@ static zend_mm_heap *zend_mm_init(void) #endif zend_mm_init_key(heap); #if ZEND_MM_LIMIT - heap->limit = (size_t)Z_L(-1) >> 1; + heap->limit = (size_t)-1 >> 1; heap->overflow = 0; #endif #if ZEND_MM_CUSTOM @@ -2426,7 +2426,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap) repeated = zend_mm_find_leaks_huge(heap, list); total += 1 + repeated; if (repeated) { - zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(uintptr_t)repeated); + zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, ZEND_ULONG2PTR(repeated)); } heap->huge_list = list = list->next; @@ -2465,7 +2465,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap) zend_mm_find_leaks(heap, p, i + bin_pages[bin_num], &leak); total += 1 + repeated; if (repeated) { - zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(uintptr_t)repeated); + zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, ZEND_ULONG2PTR(repeated)); } } dbg = (zend_mm_debug_info*)((char*)dbg + bin_data_size[bin_num]); @@ -2491,7 +2491,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap) repeated = zend_mm_find_leaks(heap, p, i + pages_count, &leak); total += 1 + repeated; if (repeated) { - zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(uintptr_t)repeated); + zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, ZEND_ULONG2PTR(repeated)); } i += pages_count; } @@ -3079,14 +3079,14 @@ static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void) #if ZEND_MM_CUSTOM static zend_always_inline void tracked_add(zend_mm_heap *heap, void *ptr, size_t size) { zval size_zv; - zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2; - ZEND_ASSERT((void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2) == ptr); + zend_ulong h = ZEND_PTR2ULONG(ptr) >> ZEND_MM_ALIGNMENT_LOG2; + ZEND_ASSERT(ZEND_ULONG2PTR(h << ZEND_MM_ALIGNMENT_LOG2) == ptr); ZVAL_LONG(&size_zv, size); zend_hash_index_add_new(heap->tracked_allocs, h, &size_zv); } static zend_always_inline zval *tracked_get_size_zv(zend_mm_heap *heap, void *ptr) { - zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2; + zend_ulong h = ZEND_PTR2ULONG(ptr) >> ZEND_MM_ALIGNMENT_LOG2; zval *size_zv = zend_hash_index_find(heap->tracked_allocs, h); ZEND_ASSERT(size_zv && "Trying to free pointer not allocated through ZendMM"); return size_zv; @@ -3172,7 +3172,7 @@ static void tracked_free_all(zend_mm_heap *heap) { HashTable *tracked_allocs = heap->tracked_allocs; zend_ulong h; ZEND_HASH_FOREACH_NUM_KEY(tracked_allocs, h) { - void *ptr = (void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2); + void *ptr = ZEND_ULONG2PTR(h << ZEND_MM_ALIGNMENT_LOG2); free(ptr); } ZEND_HASH_FOREACH_END(); } @@ -3383,7 +3383,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) zend_mm_heap *mm_heap = alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap)); memset(mm_heap, 0, sizeof(zend_mm_heap)); mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD; - mm_heap->limit = (size_t)Z_L(-1) >> 1; + mm_heap->limit = (size_t)-1 >> 1; mm_heap->overflow = 0; if (!tracked) { @@ -3606,7 +3606,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void #endif zend_mm_init_key(heap); #if ZEND_MM_LIMIT - heap->limit = (size_t)Z_L(-1) >> 1; + heap->limit = (size_t)-1 >> 1; heap->overflow = 0; #endif #if ZEND_MM_CUSTOM diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 317114265c57..57b37d35c7d7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -12952,7 +12952,7 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ } else if (Z_TYPE_P(dim) != IS_STRING || is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL, 1) != IS_LONG) { return; } - if (offset < 0 || (size_t)offset >= Z_STRLEN_P(container)) { + if (offset < 0 || ZEND_SIZE_T_LTE_ZEND_LONG(Z_STRLEN_P(container), offset)) { return; } c = (uint8_t) Z_STRVAL_P(container)[offset]; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 14a340ffee37..9a3e0f86da96 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2160,11 +2160,11 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, } } - if ((size_t)offset >= ZSTR_LEN(s)) { + if (ZEND_SIZE_T_LTE_ZEND_LONG(ZSTR_LEN(s), offset)) { /* Extend string if needed */ - zend_long old_len = ZSTR_LEN(s); + size_t old_len = ZSTR_LEN(s); ZVAL_NEW_STR(str, zend_string_extend(s, (size_t)offset + 1, 0)); - memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len); + memset(Z_STRVAL_P(str) + old_len, ' ', (size_t)offset - old_len); Z_STRVAL_P(str)[offset+1] = 0; } else { zend_string_forget_hash_val(Z_STR_P(str)); @@ -3150,7 +3150,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, c } out: - if (UNEXPECTED(ZSTR_LEN(str) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) { + if (UNEXPECTED(ZEND_SIZE_T_LT_ZEND_ULONG(ZSTR_LEN(str), ((offset < 0) ? -(zend_ulong)offset : ((zend_ulong)offset + 1))))) { if (type != BP_VAR_IS) { zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset); ZVAL_EMPTY_STRING(result); @@ -3311,7 +3311,7 @@ static zend_never_inline bool ZEND_FASTCALL zend_isset_dim_slow(const zval *cont if (UNEXPECTED(lval < 0)) { /* Handle negative offset */ lval += (zend_long)Z_STRLEN_P(container); } - if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) { + if (EXPECTED(lval >= 0) && ZEND_SIZE_T_GT_ZEND_LONG(Z_STRLEN_P(container), lval)) { return 1; } else { return 0; @@ -3350,7 +3350,7 @@ static zend_never_inline bool ZEND_FASTCALL zend_isempty_dim_slow(const zval *co if (UNEXPECTED(lval < 0)) { /* Handle negative offset */ lval += (zend_long)Z_STRLEN_P(container); } - if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) { + if (EXPECTED(lval >= 0) && ZEND_SIZE_T_GT_ZEND_LONG(Z_STRLEN_P(container), lval)) { return (Z_STRVAL_P(container)[lval] == '0'); } else { return 1; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index b48352a5aaf3..5cb9ea3e8a42 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1241,7 +1241,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * ALLOC_HASHTABLE(CG(unlinked_uses)); zend_hash_init(CG(unlinked_uses), 0, NULL, NULL, 0); } - zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_ulong)(uintptr_t)ce); + zend_hash_index_add_empty_element(CG(unlinked_uses), ZEND_PTR2ULONG(ce)); return ce; } return NULL; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b9c77e4f0f6a..d960ae7d32f1 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -178,7 +178,7 @@ static void zend_generator_remove_child(zend_generator_node *node, zend_generato node->child.single = NULL; } else { HashTable *ht = node->child.ht; - zend_hash_index_del(ht, (zend_ulong)(uintptr_t) child); + zend_hash_index_del(ht, ZEND_PTR2ULONG(child)); if (node->children == 2) { zend_generator *other_child; ZEND_HASH_FOREACH_PTR(ht, other_child) { @@ -553,11 +553,11 @@ static void zend_generator_add_child(zend_generator *generator, zend_generator * HashTable *ht = emalloc(sizeof(HashTable)); zend_hash_init(ht, 0, NULL, NULL, 0); zend_hash_index_add_new_ptr(ht, - (zend_ulong) node->child.single, node->child.single); + ZEND_PTR2ULONG(node->child.single), node->child.single); node->child.ht = ht; } - zend_hash_index_add_new_ptr(node->child.ht, (zend_ulong)(uintptr_t) child, child); + zend_hash_index_add_new_ptr(node->child.ht, ZEND_PTR2ULONG(child), child); } ++node->children; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 4424c9a1a3ab..c5294a1ae269 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3372,7 +3372,7 @@ static void check_unrecoverable_load_failure(const zend_class_entry *ce) { * a dependence on the inheritance hierarchy of this specific class. Instead we fall back to * a fatal error, as would happen if we did not allow exceptions in the first place. */ if (CG(unlinked_uses) - && zend_hash_index_del(CG(unlinked_uses), (zend_ulong)(uintptr_t)ce) == SUCCESS) { + && zend_hash_index_del(CG(unlinked_uses), ZEND_PTR2ULONG(ce)) == SUCCESS) { zend_exception_uncaught_error( "During inheritance of %s with variance dependencies", ZSTR_VAL(ce->name)); } @@ -3667,7 +3667,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string } if (CG(unlinked_uses)) { - zend_hash_index_del(CG(unlinked_uses), (zend_ulong)(uintptr_t) ce); + zend_hash_index_del(CG(unlinked_uses), ZEND_PTR2ULONG(ce)); } orig_linking_class = CG(current_linking_class); diff --git a/Zend/zend_long.h b/Zend/zend_long.h index 303bacd03d4c..e95be767b636 100644 --- a/Zend/zend_long.h +++ b/Zend/zend_long.h @@ -22,7 +22,7 @@ #include /* This is the heart of the whole int64 enablement in zval. */ -#if defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64) +#ifdef ZEND_INT64 # define ZEND_ENABLE_ZVAL_LONG64 1 #endif @@ -37,6 +37,12 @@ typedef int64_t zend_off_t; # define Z_L(i) INT64_C(i) # define Z_UL(i) UINT64_C(i) # define SIZEOF_ZEND_LONG 8 +# define ZEND_PTR2ULONG(ptr) ((zend_ulong)(uintptr_t)(ptr)) +# define ZEND_ULONG2PTR(i) \ + ( (UNEXPECTED((i) > (zend_ulong)UINTPTR_MAX)) \ + ? (assert(!"zend_ulong out of pointer range"), NULL) \ + : (void *)(uintptr_t)(i) \ + ) #else typedef int32_t zend_long; typedef uint32_t zend_ulong; @@ -47,6 +53,8 @@ typedef int32_t zend_off_t; # define Z_L(i) INT32_C(i) # define Z_UL(i) UINT32_C(i) # define SIZEOF_ZEND_LONG 4 +# define ZEND_PTR2ULONG(ptr) ((zend_ulong)(uintptr_t)(ptr)) +# define ZEND_ULONG2PTR(i) ((void *)(uintptr_t)(i)) #endif diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 8ca6d212fd72..aa3757a184ea 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -450,7 +450,7 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c *info_ptr = property_info; } if (cache_slot) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)(uintptr_t)offset); + CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*) offset); CACHE_PTR_EX(cache_slot + 2, property_info); } return offset; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 27aa4fdb0486..d4dc6dad5eda 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -522,11 +522,11 @@ ZEND_API void zend_reset_lc_ctype_locale(void); #define ZVAL_OFFSETOF_TYPE \ (offsetof(zval, u1.type_info) - offsetof(zval, value)) -#if defined(HAVE_ASM_GOTO) && !__has_feature(memory_sanitizer) -# define ZEND_USE_ASM_ARITHMETIC 1 -#else +//#if defined(HAVE_ASM_GOTO) && !__has_feature(memory_sanitizer) +//# define ZEND_USE_ASM_ARITHMETIC 1 +//#else # define ZEND_USE_ASM_ARITHMETIC 0 -#endif +//#endif static zend_always_inline void fast_long_increment_function(zval *op1) { diff --git a/Zend/zend_range_check.h b/Zend/zend_range_check.h index 8db867434399..cc28c95f492d 100644 --- a/Zend/zend_range_check.h +++ b/Zend/zend_range_check.h @@ -58,9 +58,24 @@ #endif /* Comparison zend_long vs size_t */ -#define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) > (size_t)(zlong)) -#define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) >= (size_t)(zlong)) -#define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) < (size_t)(zlong)) -#define ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) <= (size_t)(zlong)) +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG +# define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || ((zlong) < SIZE_MAX && (size) > (size_t)(zlong))) +# define ZEND_SIZE_T_GT_ZEND_ULONG(size, zulong) (zulong < SIZE_MAX && (size) > (size_t)(zulong)) +# define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || ((zlong) <= SIZE_MAX && (size) >= (size_t)(zlong))) +# define ZEND_SIZE_T_GTE_ZEND_ULONG(size, zulong) ((zulong) <= SIZE_MAX && (size) >= (size_t)(zulong)) +# define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) >= SIZE_MAX || ((zlong) > 0 && (size) < (size_t)(zlong))) +# define ZEND_SIZE_T_LT_ZEND_ULONG(size, zulong) ((zulong) >= SIZE_MAX || (size) < (size_t)(zulong)) +# define ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) ((zlong) > SIZE_MAX || ((zlong) >= 0 && (size) <= (size_t)(zlong))) +# define ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) ((zulong) > SIZE_MAX || (size) <= (size_t)(zlong)) +#else +# define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) > (size_t)(zlong)) +# define ZEND_SIZE_T_GT_ZEND_ULONG(size, zulong) ((size) > (size_t)(zulong)) +# define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) >= (size_t)(zlong)) +# define ZEND_SIZE_T_GTE_ZEND_ULONG(size, zulong) ((size) >= (size_t)(zulong)) +# define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) > 0 && (size) < (size_t)(zlong)) +# define ZEND_SIZE_T_LT_ZEND_ULONG(size, zulong) ((size) < (size_t)(zulong)) +# define ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) ((zlong) >= 0 && (size) <= (size_t)(zlong)) +# define ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) ((size) <= (size_t)(zulong)) +#endif #endif /* ZEND_RANGE_CHECK_H */ diff --git a/Zend/zend_string.c b/Zend/zend_string.c index b1b4a0e17a69..ea4deac2f536 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -425,7 +425,7 @@ ZEND_API zend_never_inline NOIPA bool ZEND_FASTCALL zend_string_equal_val(const const char *ptr = ZSTR_VAL(s1); uintptr_t delta = (uintptr_t) s2 - (uintptr_t) s1; size_t len = ZSTR_LEN(s1); - zend_ulong ret; + size_t ret; __asm__ ( "0:\n\t" @@ -456,14 +456,13 @@ ZEND_API zend_never_inline NOIPA bool ZEND_FASTCALL zend_string_equal_val(const : "cc"); return ret; } - #elif defined(__GNUC__) && defined(__x86_64__) && !defined(__ILP32__) ZEND_API zend_never_inline NOIPA bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2) { const char *ptr = ZSTR_VAL(s1); uintptr_t delta = (uintptr_t) s2 - (uintptr_t) s1; size_t len = ZSTR_LEN(s1); - zend_ulong ret; + size_t ret; __asm__ ( "0:\n\t" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0e35b5bb95fa..edad68478151 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -9853,7 +9853,7 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT) } else { /* Rotate the key for better hash distribution. */ const int shift = sizeof(size_t) == 4 ? 6 : 7; - zend_ulong key = (zend_ulong)(uintptr_t)call->func; + zend_ulong key = ZEND_PTR2ULONG(call->func); key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c6158bd507d9..fa7aa5091a08 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -37662,7 +37662,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONV } else { /* Rotate the key for better hash distribution. */ const int shift = sizeof(size_t) == 4 ? 6 : 7; - zend_ulong key = (zend_ulong)(uintptr_t)call->func; + zend_ulong key = ZEND_PTR2ULONG(call->func); key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { @@ -90305,7 +90305,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_S } else { /* Rotate the key for better hash distribution. */ const int shift = sizeof(size_t) == 4 ? 6 : 7; - zend_ulong key = (zend_ulong)(uintptr_t)call->func; + zend_ulong key = ZEND_PTR2ULONG(call->func); key = (key >> shift) | (key << ((sizeof(key) * 8) - shift)); zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key); if (Z_TYPE_P(closure_zv) == IS_NULL) { @@ -123271,7 +123271,7 @@ static void init_opcode_serialiser(void) Z_TYPE_INFO(tmp) = IS_LONG; for (i = 0; i < zend_handlers_count; i++) { Z_LVAL(tmp) = i; - zend_hash_index_add(zend_handlers_table, (zend_ulong)(uintptr_t)zend_opcode_handlers[i], &tmp); + zend_hash_index_add(zend_handlers_table, ZEND_PTR2ULONG(zend_opcode_handlers[i]), &tmp); } } @@ -123282,7 +123282,7 @@ ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op) if (!zend_handlers_table) { init_opcode_serialiser(); } - zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, ZEND_PTR2ULONG(op->handler)); ZEND_ASSERT(zv != NULL); op->handler = (zend_vm_opcode_handler_t)(uintptr_t)Z_LVAL_P(zv); } @@ -123300,7 +123300,7 @@ ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *o if (!zend_handlers_table) { init_opcode_serialiser(); } - zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, ZEND_PTR2ULONG(op->handler)); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #elif ZEND_VM_KIND == ZEND_VM_KIND_CALL diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 4e8f28270bae..ce81be97109e 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -114,7 +114,7 @@ static void init_opcode_serialiser(void) Z_TYPE_INFO(tmp) = IS_LONG; for (i = 0; i < zend_handlers_count; i++) { Z_LVAL(tmp) = i; - zend_hash_index_add(zend_handlers_table, (zend_ulong)(uintptr_t)zend_opcode_handlers[i], &tmp); + zend_hash_index_add(zend_handlers_table, ZEND_PTR2ULONG(zend_opcode_handlers[i]), &tmp); } } @@ -125,7 +125,7 @@ ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op) if (!zend_handlers_table) { init_opcode_serialiser(); } - zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, ZEND_PTR2ULONG(op->handler)); ZEND_ASSERT(zv != NULL); op->handler = (zend_vm_opcode_handler_t)(uintptr_t)Z_LVAL_P(zv); } @@ -143,7 +143,7 @@ ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *o if (!zend_handlers_table) { init_opcode_serialiser(); } - zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, ZEND_PTR2ULONG(op->handler)); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #elif ZEND_VM_KIND == ZEND_VM_KIND_CALL diff --git a/Zend/zend_vm_trace_map.h b/Zend/zend_vm_trace_map.h index 18c705b454d5..c8197450ee70 100644 --- a/Zend/zend_vm_trace_map.h +++ b/Zend/zend_vm_trace_map.h @@ -19,7 +19,7 @@ #include "zend_sort.h" #define GEN_MAP(n, name) do { \ - ZVAL_LONG(&tmp, (zend_long)(uintptr_t)zend_opcode_handlers[n]); \ + ZVAL_LONG(&tmp, ZEND_PTR2ULONG(zend_opcode_handlers[n])); \ zend_hash_str_add(&vm_trace_ht, #name, sizeof(#name) - 1, &tmp); \ } while (0); diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index ad0308f44e20..06ab59116e9f 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -107,15 +107,15 @@ static void zend_weakref_register(zend_object *object, void *payload) { void *tagged_ptr = Z_PTR_P(zv); if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_HT) { HashTable *ht = ZEND_WEAKREF_GET_PTR(tagged_ptr); - zend_hash_index_add_new_ptr(ht, (zend_ulong)(uintptr_t) payload, payload); + zend_hash_index_add_new_ptr(ht, ZEND_PTR2ULONG(payload), payload); return; } /* Convert simple pointer to hashtable. */ HashTable *ht = emalloc(sizeof(HashTable)); zend_hash_init(ht, 0, NULL, NULL, 0); - zend_hash_index_add_new_ptr(ht, (zend_ulong)(uintptr_t) tagged_ptr, tagged_ptr); - zend_hash_index_add_new_ptr(ht, (zend_ulong)(uintptr_t) payload, payload); + zend_hash_index_add_new_ptr(ht, ZEND_PTR2ULONG(tagged_ptr), tagged_ptr); + zend_hash_index_add_new_ptr(ht, ZEND_PTR2ULONG(payload), payload); /* Replace the single WeakMap or WeakReference entry in EG(weakrefs) with a HashTable with 2 entries in place. */ ZVAL_PTR(zv, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_HT)); } @@ -144,11 +144,11 @@ static void zend_weakref_unregister(zend_object *object, void *payload, bool wea HashTable *ht = ptr; #if ZEND_DEBUG - void *old_payload = zend_hash_index_find_ptr(ht, (zend_ulong)(uintptr_t) payload); + void *old_payload = zend_hash_index_find_ptr(ht, ZEND_PTR2ULONG(payload)); ZEND_ASSERT(old_payload && "Weakref not registered?"); ZEND_ASSERT(old_payload == payload); #endif - zend_hash_index_del(ht, (zend_ulong)(uintptr_t) payload); + zend_hash_index_del(ht, ZEND_PTR2ULONG(payload)); if (zend_hash_num_elements(ht) == 0) { GC_DEL_FLAGS(object, IS_OBJ_WEAKLY_REFERENCED); zend_hash_destroy(ht); From 825dc2ac2d712374321924308ef56187bfcce7d6 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sat, 8 Aug 2026 07:45:17 +0200 Subject: [PATCH 02/12] Fix alignment of Bucket --- Zend/zend_types.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Zend/zend_types.h b/Zend/zend_types.h index b30f53d7f917..4c8c2fb324b1 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -383,11 +383,13 @@ struct _zend_string { char val[1]; }; -typedef struct _Bucket { +/* ZEND_BIND_* stores byte offsets into arData in opline extended values, with + * flags encoded in the low three bits. */ +typedef ZEND_SET_ALIGNED(8, struct _Bucket { zval val; zend_ulong h; /* hash value (or numeric index) */ zend_string *key; /* string key or NULL for numerics */ -} Bucket; +}) Bucket; typedef struct _zend_array HashTable; From b69bd466d5d270bc48128d0fc95940f28d96c937 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 14 Aug 2026 18:04:39 +0200 Subject: [PATCH 03/12] Added range checks helpers zend_long vs. size_t --- Zend/zend_range_check.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Zend/zend_range_check.h b/Zend/zend_range_check.h index cc28c95f492d..e6e552fa987f 100644 --- a/Zend/zend_range_check.h +++ b/Zend/zend_range_check.h @@ -57,8 +57,12 @@ # define ZEND_SIZE_T_UINT_OVFL(size) (0) #endif -/* Comparison zend_long vs size_t */ +/* zend_long vs size_t checks. */ #if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG +# define ZEND_LONG_SIZE_T_OVFL(zlong) UNEXPECTED((zlong) > (zend_long)SIZE_MAX) +# define ZEND_LONG_FITS_SIZE_T(zlong) EXPECTED((zlong) >= 0 && (zlong) <= (zend_long)SIZE_MAX) +# define ZEND_LONG_NOT_FITS_SIZE_T(zlong) UNEXPECTED((zlong) < 0 || (zlong) > (zend_long)SIZE_MAX) + # define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || ((zlong) < SIZE_MAX && (size) > (size_t)(zlong))) # define ZEND_SIZE_T_GT_ZEND_ULONG(size, zulong) (zulong < SIZE_MAX && (size) > (size_t)(zulong)) # define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || ((zlong) <= SIZE_MAX && (size) >= (size_t)(zlong))) @@ -66,8 +70,12 @@ # define ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) ((zlong) >= SIZE_MAX || ((zlong) > 0 && (size) < (size_t)(zlong))) # define ZEND_SIZE_T_LT_ZEND_ULONG(size, zulong) ((zulong) >= SIZE_MAX || (size) < (size_t)(zulong)) # define ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) ((zlong) > SIZE_MAX || ((zlong) >= 0 && (size) <= (size_t)(zlong))) -# define ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) ((zulong) > SIZE_MAX || (size) <= (size_t)(zlong)) +# define ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) ((zulong) > SIZE_MAX || (size) <= (size_t)(zulong)) #else +# define ZEND_LONG_SIZE_T_OVFL(zlong) (0) +# define ZEND_LONG_FITS_SIZE_T(zlong) EXPECTED((zlong) >= 0) +# define ZEND_LONG_NOT_FITS_SIZE_T(zlong) UNEXPECTED((zlong) < 0) + # define ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) > (size_t)(zlong)) # define ZEND_SIZE_T_GT_ZEND_ULONG(size, zulong) ((size) > (size_t)(zulong)) # define ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) ((zlong) < 0 || (size) >= (size_t)(zlong)) @@ -78,4 +86,13 @@ # define ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) ((size) <= (size_t)(zulong)) #endif +# define ZEND_LONG_GT_SIZE_T(zlong, size) ZEND_SIZE_T_LT_ZEND_LONG(size, zlong) +# define ZEND_ULONG_GT_SIZE_T(zulong, size) ZEND_SIZE_T_LT_ZEND_ULONG(size, zulong) +# define ZEND_LONG_GTE_SIZE_T(zlong, size) ZEND_SIZE_T_LTE_ZEND_LONG(size, zlong) +# define ZEND_ULONG_GTE_SIZE_T(zulong, size) ZEND_SIZE_T_LTE_ZEND_ULONG(size, zulong) +# define ZEND_LONG_LT_SIZE_T(zlong, size) ZEND_SIZE_T_GT_ZEND_LONG(size, zlong) +# define ZEND_ULONG_LT_SIZE_T(zulong, size) ZEND_SIZE_T_GT_ZEND_ULONG(size, zulong) +# define ZEND_LONG_LTE_SIZE_T(zlong, size) ZEND_SIZE_T_GTE_ZEND_LONG(size, zlong) +# define ZEND_ULONG_LTE_SIZE_T(zulong, size) ZEND_SIZE_T_GTE_ZEND_ULONG(size, zulong) + #endif /* ZEND_RANGE_CHECK_H */ From 3dfa376d5995040afd8054ceeaf14b568c364682 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sat, 8 Aug 2026 08:10:03 +0200 Subject: [PATCH 04/12] Added PHP_SYS_SIZE from SIZEOF_SIZE_T --- main/main.stub.php | 5 +++++ main/main_arginfo.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/main/main.stub.php b/main/main.stub.php index af19a7f73731..63d0dc1e69ed 100644 --- a/main/main.stub.php +++ b/main/main.stub.php @@ -171,6 +171,11 @@ * @cvalue SIZEOF_ZEND_LONG */ const PHP_INT_SIZE = UNKNOWN; +/** + * @var int + * @cvalue SIZEOF_SIZE_T + */ +const PHP_SYS_SIZE = UNKNOWN; /** * @var int * @cvalue FD_SETSIZE diff --git a/main/main_arginfo.h b/main/main_arginfo.h index d2bd2725ec41..c94ed4624f90 100644 --- a/main/main_arginfo.h +++ b/main/main_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit main.stub.php instead. - * Stub hash: 22b4c7412680888c122886bccd21e3d38953ce33 */ + * Stub hash: 11477000f37eb06d583127414783f8330e92ba8a */ static void register_main_symbols(int module_number) { @@ -39,6 +39,7 @@ static void register_main_symbols(int module_number) REGISTER_LONG_CONSTANT("PHP_INT_MAX", ZEND_LONG_MAX, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_INT_MIN", ZEND_LONG_MIN, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_INT_SIZE", SIZEOF_ZEND_LONG, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHP_SYS_SIZE", SIZEOF_SIZE_T, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_FD_SETSIZE", FD_SETSIZE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_FLOAT_DIG", DBL_DIG, CONST_PERSISTENT); REGISTER_DOUBLE_CONSTANT("PHP_FLOAT_EPSILON", DBL_EPSILON, CONST_PERSISTENT); From 4e6ee50160246db395bf2fd2ddd9f910e39c3f54 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sat, 8 Aug 2026 08:11:08 +0200 Subject: [PATCH 05/12] Fixed Zend/tests/fibers/get-return-after-bailout.phpt --- Zend/tests/fibers/get-return-after-bailout.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zend/tests/fibers/get-return-after-bailout.phpt b/Zend/tests/fibers/get-return-after-bailout.phpt index 79ab70c98baa..0d78ba2376c4 100644 --- a/Zend/tests/fibers/get-return-after-bailout.phpt +++ b/Zend/tests/fibers/get-return-after-bailout.phpt @@ -16,7 +16,8 @@ register_shutdown_function(static function (): void { }); $fiber = new Fiber(static function (): void { - str_repeat('X', PHP_INT_MAX); + $allocSize = PHP_INT_SIZE <= PHP_SYS_SIZE ? PHP_INT_MAX : 2 ** (PHP_SYS_SIZE * 8 - 1) - 1; + str_repeat('X', $allocSize); }); $fiber->start(); From 5d1702d605ab0c248a0ad0ac6b17b48e5b0f412f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:37:21 +0200 Subject: [PATCH 06/12] Fix ext/standard --- ext/standard/crypt_sha256.c | 2 +- ext/standard/crypt_sha512.c | 2 +- ext/standard/file.c | 47 +++++++-- ext/standard/head.c | 5 +- ext/standard/head.h | 2 +- ext/standard/math.c | 6 +- ext/standard/metaphone.c | 5 +- ext/standard/streamsfuncs.c | 70 ++++++++++--- ext/standard/string.c | 97 ++++++++++++------- .../tests/file/fgetcsv_length_sizet.phpt | 21 ++++ .../tests/file/fgets_length_sizet.phpt | 21 ++++ .../file/file_get_contents_length_sizet.phpt | 19 ++++ .../tests/file/fread_length_sizet.phpt | 21 ++++ .../tests/file/ftruncate_error_sizet.phpt | 51 ++++++++++ ext/standard/tests/file/fwrite.phpt | 2 +- ext/standard/tests/file/umask_variation1.phpt | 2 +- ext/standard/tests/file/umask_variation2.phpt | 2 +- ext/standard/tests/streams/bug61115-1.phpt | 2 +- ...stream_copy_to_stream_maxlength_sizet.phpt | 25 +++++ .../stream_get_contents_maxlength_sizet.phpt | 23 +++++ .../streams/stream_get_line_length_sizet.phpt | 23 +++++ .../streams/stream_set_read_buffer_sizet.phpt | 21 ++++ .../stream_set_write_buffer_sizet.phpt | 21 ++++ .../stream_socket_recvfrom_length_sizet.phpt | 21 ++++ ext/standard/tests/strings/bug72146.phpt | 4 +- .../tests/strings/chunk_split_variation8.phpt | 7 +- ext/standard/tests/strings/gh15613.phpt | 2 +- .../strings/metaphone_max_phonemes_sizet.phpt | 20 ++++ .../sprintf_rope_optimization_004.phpt | 16 +-- .../tests/strings/str_pad_variation1.phpt | 11 ++- .../tests/strings/str_pad_variation2.phpt | 2 +- .../tests/strings/str_pad_variation5.phpt | 24 ++--- .../tests/strings/str_repeat_sizet.phpt | 47 +++++++++ .../tests/strings/str_split_variation6.phpt | 12 +++ ext/standard/tests/strings/stripos_error.phpt | 14 +++ ext/standard/tests/strings/strpos_error.phpt | 45 +++++++++ .../tests/strings/strripos_error.phpt | 45 +++++++++ ext/standard/tests/strings/strrpos_error.phpt | 45 +++++++++ ext/standard/tests/strings/substr.phpt | 18 ++++ .../tests/strings/substr_compare.phpt | 19 +++- .../tests/strings/substr_count_error.phpt | 34 +++++++ .../substr_replace_large_offset_length.phpt | 39 ++++++++ main/streams/memory.c | 2 + 43 files changed, 811 insertions(+), 106 deletions(-) create mode 100644 ext/standard/tests/file/fgetcsv_length_sizet.phpt create mode 100644 ext/standard/tests/file/fgets_length_sizet.phpt create mode 100644 ext/standard/tests/file/file_get_contents_length_sizet.phpt create mode 100644 ext/standard/tests/file/fread_length_sizet.phpt create mode 100644 ext/standard/tests/file/ftruncate_error_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_copy_to_stream_maxlength_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_get_contents_maxlength_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_get_line_length_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_set_read_buffer_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_set_write_buffer_sizet.phpt create mode 100644 ext/standard/tests/streams/stream_socket_recvfrom_length_sizet.phpt create mode 100644 ext/standard/tests/strings/metaphone_max_phonemes_sizet.phpt create mode 100644 ext/standard/tests/strings/str_repeat_sizet.phpt create mode 100644 ext/standard/tests/strings/strpos_error.phpt create mode 100644 ext/standard/tests/strings/strripos_error.phpt create mode 100644 ext/standard/tests/strings/strrpos_error.phpt create mode 100644 ext/standard/tests/strings/substr_replace_large_offset_length.phpt diff --git a/ext/standard/crypt_sha256.c b/ext/standard/crypt_sha256.c index 3f3d9cdeb03c..d2488b185397 100644 --- a/ext/standard/crypt_sha256.c +++ b/ext/standard/crypt_sha256.c @@ -510,7 +510,7 @@ char * php_sha256_crypt_r(const char *key, const char *salt, char *buffer, int b if (rounds_custom) { #ifdef PHP_WIN32 - int n = _snprintf(cp, MAX(0, buflen), "%s" ZEND_ULONG_FMT "$", sha256_rounds_prefix, rounds); + int n = _snprintf(cp, MAX(0, buflen), "%s%zu$", sha256_rounds_prefix, rounds); #else int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha256_rounds_prefix, rounds); #endif diff --git a/ext/standard/crypt_sha512.c b/ext/standard/crypt_sha512.c index 4a308e2f9af2..04f8448ff6d5 100644 --- a/ext/standard/crypt_sha512.c +++ b/ext/standard/crypt_sha512.c @@ -549,7 +549,7 @@ php_sha512_crypt_r(const char *key, const char *salt, char *buffer, int buflen) if (rounds_custom) { #ifdef PHP_WIN32 - int n = _snprintf(cp, MAX(0, buflen), "%s" ZEND_ULONG_FMT "$", sha512_rounds_prefix, rounds); + int n = _snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds); #else int n = snprintf(cp, MAX(0, buflen), "%s%zu$", sha512_rounds_prefix, rounds); #endif diff --git a/ext/standard/file.c b/ext/standard/file.c index d6a8b9f1d0ea..a6f5f7653ffd 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -381,7 +381,8 @@ PHP_FUNCTION(file_get_contents) bool use_include_path = 0; php_stream *stream; zend_long offset = 0; - zend_long maxlen; + zend_long maxlen_zl; + size_t maxlen; bool maxlen_is_null = 1; zval *zcontext = NULL; php_stream_context *context = NULL; @@ -394,14 +395,19 @@ PHP_FUNCTION(file_get_contents) Z_PARAM_BOOL(use_include_path) Z_PARAM_RESOURCE_OR_NULL(zcontext) Z_PARAM_LONG(offset) - Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) + Z_PARAM_LONG_OR_NULL(maxlen_zl, maxlen_is_null) ZEND_PARSE_PARAMETERS_END(); if (maxlen_is_null) { - maxlen = (ssize_t) PHP_STREAM_COPY_ALL; - } else if (maxlen < 0) { + maxlen = PHP_STREAM_COPY_ALL; + } else if (UNEXPECTED(maxlen_zl < 0)) { zend_argument_value_error(5, "must be greater than or equal to 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(maxlen_zl)) { + zend_argument_value_error(5, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } else { + maxlen = (size_t) maxlen_zl; } php_stream_error_operation_begin(); @@ -505,10 +511,12 @@ PHP_FUNCTION(file_put_contents) if (php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL, &len) != SUCCESS) { numbytes = -1; } else { +#if SIZEOF_SIZE_T >= SIZEOF_ZEND_LONG if (len > ZEND_LONG_MAX) { php_error_docref(NULL, E_WARNING, "content truncated from %zu to " ZEND_LONG_FMT " bytes", len, ZEND_LONG_MAX); len = ZEND_LONG_MAX; } +#endif numbytes = len; } break; @@ -908,13 +916,16 @@ PHPAPI PHP_FUNCTION(fgets) RETVAL_STRINGL(buf, line_len); efree(buf); } else { - if (len <= 0) { + if (UNEXPECTED(len <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(len)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } - str = zend_string_alloc(len, 0); - buf = php_stream_get_line(stream, ZSTR_VAL(str), len, &line_len); + str = zend_string_alloc((size_t) len, 0); + buf = php_stream_get_line(stream, ZSTR_VAL(str), (size_t) len, &line_len); php_stream_error_operation_end_for_stream(stream); if (buf == NULL) { zend_string_efree(str); @@ -1019,7 +1030,11 @@ PHPAPI PHP_FUNCTION(fwrite) } else if (maxlen <= 0) { num_bytes = 0; } else { +#if SIZEOF_SIZE_T >= SIZEOF_ZEND_LONG num_bytes = MIN((size_t) maxlen, inputlen); +#else + num_bytes = MIN(maxlen, (zend_long) inputlen); +#endif } if (!num_bytes) { @@ -1366,9 +1381,12 @@ PHP_FUNCTION(ftruncate) Z_PARAM_LONG(size) ZEND_PARSE_PARAMETERS_END(); - if (size < 0) { + if (UNEXPECTED(size < 0)) { zend_argument_value_error(2, "must be greater than or equal to 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(size)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } php_stream_error_operation_begin(); @@ -1614,9 +1632,12 @@ PHPAPI PHP_FUNCTION(fread) Z_PARAM_LONG(len) ZEND_PARSE_PARAMETERS_END(); - if (len <= 0) { + if (UNEXPECTED(len <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(len)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } php_stream_error_operation_begin(); @@ -1870,9 +1891,15 @@ PHP_FUNCTION(fgetcsv) if (len_is_null || len == 0) { len = -1; - } else if (len < 0 || len > (ZEND_LONG_MAX - 1)) { +#if SIZEOF_SIZE_T >= SIZEOF_ZEND_LONG + } else if (UNEXPECTED(len < 0 || len > (ZEND_LONG_MAX - 1))) { zend_argument_value_error(2, "must be between 0 and " ZEND_LONG_FMT, (ZEND_LONG_MAX - 1)); RETURN_THROWS(); +#else + } else if (UNEXPECTED(len < 0 || len > (SIZE_MAX - 1))) { + zend_argument_value_error(2, "must be between 0 and %zu", (SIZE_MAX - 1)); + RETURN_THROWS(); +#endif } php_stream_error_operation_begin(); diff --git a/ext/standard/head.c b/ext/standard/head.c index 34a22327b5e7..3f524820cb9c 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -82,7 +82,7 @@ PHPAPI bool php_is_valid_samesite_value(zend_string *value) } #define ILLEGAL_COOKIE_CHARACTER "\",\", \";\", \" \", \"\\t\", \"\\r\", \"\\n\", \"\\013\", or \"\\014\"" -PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires, +PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, zend_long expires, zend_string *path, zend_string *domain, bool secure, bool httponly, zend_string *samesite, bool partitioned, bool url_encode) { @@ -115,7 +115,8 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e get_active_function_name()); return FAILURE; } -#ifdef ZEND_ENABLE_ZVAL_LONG64 + +#if SIZEOF_ZEND_LONG >= 8 if (expires >= 253402300800) { zend_value_error("%s(): \"expires\" option cannot have a year greater than 9999", get_active_function_name()); diff --git a/ext/standard/head.h b/ext/standard/head.h index 8b91371a46e2..95b43342032f 100644 --- a/ext/standard/head.h +++ b/ext/standard/head.h @@ -29,7 +29,7 @@ PHPAPI bool php_is_valid_samesite_value(zend_string *value); extern PHP_RINIT_FUNCTION(head); PHPAPI bool php_header(void); -PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires, +PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, zend_long expires, zend_string *path, zend_string *domain, bool secure, bool httponly, zend_string *samesite, bool partitioned, bool url_encode); diff --git a/ext/standard/math.c b/ext/standard/math.c index 20286870c7c9..4fda7f2785ad 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -1283,8 +1283,8 @@ PHPAPI zend_string *_php_math_number_format_long(zend_long num, zend_long dec, c 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, #if SIZEOF_ZEND_LONG == 8 - 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, - 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000ul + Z_UL(10000000000), Z_UL(100000000000), Z_UL(1000000000000), Z_UL(10000000000000), Z_UL(100000000000000), + Z_UL(1000000000000000), Z_UL(10000000000000000), Z_UL(100000000000000000), Z_UL(1000000000000000000), Z_UL(10000000000000000000) #elif SIZEOF_ZEND_LONG > 8 # error "Unknown SIZEOF_ZEND_LONG" #endif @@ -1314,7 +1314,7 @@ PHPAPI zend_string *_php_math_number_format_long(zend_long num, zend_long dec, c // rounding the number if (dec < 0) { // Check rounding to more negative places than possible - if (dec < -(sizeof(powers) / sizeof(powers[0]) - 1)) { + if (UNEXPECTED(dec < -(zend_long)(sizeof(powers) / sizeof(powers[0]) - 1))) { tmpnum = 0; } else { power = powers[-dec]; diff --git a/ext/standard/metaphone.c b/ext/standard/metaphone.c index 8f33057de5ac..e2ef3be7d787 100644 --- a/ext/standard/metaphone.c +++ b/ext/standard/metaphone.c @@ -33,9 +33,12 @@ PHP_FUNCTION(metaphone) Z_PARAM_LONG(phones) ZEND_PARSE_PARAMETERS_END(); - if (phones < 0) { + if (UNEXPECTED(phones < 0)) { zend_argument_value_error(2, "must be greater than or equal to 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(phones)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } metaphone((unsigned char *)ZSTR_VAL(str), ZSTR_LEN(str), phones, &result, 1); diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index d544e8bf5f0f..07ce7494d1f0 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -425,15 +425,18 @@ PHP_FUNCTION(stream_socket_recvfrom) ZEND_TRY_ASSIGN_REF_NULL(zremote); } - if (to_read <= 0) { + if (UNEXPECTED(to_read <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(to_read)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } - read_buf = zend_string_alloc(to_read, 0); + read_buf = zend_string_alloc((size_t) to_read, 0); php_stream_error_operation_begin(); - recvd = php_stream_xport_recvfrom(stream, ZSTR_VAL(read_buf), to_read, (int)flags, NULL, NULL, + recvd = php_stream_xport_recvfrom(stream, ZSTR_VAL(read_buf), (size_t) to_read, (int)flags, NULL, NULL, zremote ? &remote_addr : NULL); php_stream_error_operation_end_for_stream(stream); @@ -455,22 +458,28 @@ PHP_FUNCTION(stream_socket_recvfrom) PHP_FUNCTION(stream_get_contents) { php_stream *stream; - zend_long maxlen, desiredpos = -1L; + zend_long maxlen_zl, desiredpos = -1L; + size_t maxlen; bool maxlen_is_null = 1; zend_string *contents; ZEND_PARSE_PARAMETERS_START(1, 3) PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) + Z_PARAM_LONG_OR_NULL(maxlen_zl, maxlen_is_null) Z_PARAM_LONG(desiredpos) ZEND_PARSE_PARAMETERS_END(); - if (maxlen_is_null) { - maxlen = (ssize_t) PHP_STREAM_COPY_ALL; - } else if (maxlen < 0 && maxlen != (ssize_t)PHP_STREAM_COPY_ALL) { + if (maxlen_is_null || maxlen_zl == -1) { + maxlen = PHP_STREAM_COPY_ALL; + } else if (UNEXPECTED(maxlen_zl < 0)) { zend_argument_value_error(2, "must be greater than or equal to -1"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(maxlen_zl)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } else { + maxlen = (size_t) maxlen_zl; } php_stream_error_operation_begin(); @@ -496,7 +505,7 @@ PHP_FUNCTION(stream_get_contents) } } - if ((contents = php_stream_copy_to_mem(stream, maxlen, 0))) { + if ((contents = php_stream_copy_to_mem(stream, (size_t) maxlen, 0))) { RETVAL_STR(contents); } else { RETVAL_EMPTY_STRING(); @@ -509,7 +518,8 @@ PHP_FUNCTION(stream_get_contents) PHP_FUNCTION(stream_copy_to_stream) { php_stream *src, *dest; - zend_long maxlen, pos = 0; + zend_long maxlen_zl, pos = 0; + size_t maxlen; bool maxlen_is_null = 1; size_t len; zval *zcontext = NULL; @@ -519,13 +529,21 @@ PHP_FUNCTION(stream_copy_to_stream) PHP_Z_PARAM_STREAM(src) PHP_Z_PARAM_STREAM(dest) Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) + Z_PARAM_LONG_OR_NULL(maxlen_zl, maxlen_is_null) Z_PARAM_LONG(pos) Z_PARAM_RESOURCE_OR_NULL(zcontext) ZEND_PARSE_PARAMETERS_END(); - if (maxlen_is_null) { + if (maxlen_is_null || maxlen_zl == -1) { maxlen = PHP_STREAM_COPY_ALL; + } else if (UNEXPECTED(maxlen_zl < 0)) { + zend_argument_value_error(3, "must be greater than or equal to -1"); + RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(maxlen_zl)) { + zend_argument_value_error(3, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } else { + maxlen = (size_t) maxlen_zl; } php_stream_error_operation_begin(); @@ -1420,16 +1438,20 @@ PHP_FUNCTION(stream_get_line) Z_PARAM_STRING(str, str_len) ZEND_PARSE_PARAMETERS_END(); - if (max_length < 0) { + if (UNEXPECTED(max_length < 0)) { zend_argument_value_error(2, "must be greater than or equal to 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(max_length)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } + if (!max_length) { max_length = PHP_SOCK_CHUNK_SIZE; } php_stream_error_operation_begin(); - if ((buf = php_stream_get_record(stream, max_length, str, str_len))) { + if ((buf = php_stream_get_record(stream, (size_t) max_length, str, str_len))) { RETVAL_STR(buf); } else { RETVAL_FALSE; @@ -1513,7 +1535,15 @@ PHP_FUNCTION(stream_set_write_buffer) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - buff = arg2; + if (UNEXPECTED(arg2 < 0)) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(arg2)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } + + buff = (size_t) arg2; php_stream_error_operation_begin(); /* if buff is 0 then set to non-buffered */ @@ -1574,7 +1604,15 @@ PHP_FUNCTION(stream_set_read_buffer) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - buff = arg2; + if (UNEXPECTED(arg2 < 0)) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(arg2)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } + + buff = (size_t) arg2; php_stream_error_operation_begin(); /* if buff is 0 then set to non-buffered */ diff --git a/ext/standard/string.c b/ext/standard/string.c index 2d868513e4ad..868967bab4e6 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -188,7 +188,7 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, bool is_strspn) if (start < 0) { start = 0; } - } else if ((size_t) start > remain_len) { + } else if (ZEND_LONG_GT_SIZE_T(start, remain_len)) { start = remain_len; } @@ -199,7 +199,7 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, bool is_strspn) if (len < 0) { len = 0; } - } else if ((size_t) len > remain_len) { + } else if (ZEND_LONG_GT_SIZE_T(len, remain_len)) { len = remain_len; } } else { @@ -1973,7 +1973,7 @@ static zend_always_inline void _zend_strpos(zval *return_value, zend_string *hay if (offset < 0) { offset += (zend_long)ZSTR_LEN(haystack); } - if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) { + if (offset < 0 || ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -2054,7 +2054,7 @@ PHP_FUNCTION(stripos) if (offset < 0) { offset += (zend_long)ZSTR_LEN(haystack); } - if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) { + if (offset < 0 || ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -2085,14 +2085,14 @@ PHP_FUNCTION(strrpos) ZEND_PARSE_PARAMETERS_END(); if (offset >= 0) { - if ((size_t)offset > ZSTR_LEN(haystack)) { + if (ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } p = ZSTR_VAL(haystack) + (size_t)offset; e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack); } else { - if (offset < -ZEND_LONG_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { + if (offset < -ZEND_LONG_MAX || ZEND_LONG_GT_SIZE_T(-offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -2135,7 +2135,7 @@ PHP_FUNCTION(strripos) Can also avoid tolower emallocs */ char lowered; if (offset >= 0) { - if ((size_t)offset > ZSTR_LEN(haystack)) { + if (ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -2143,7 +2143,7 @@ PHP_FUNCTION(strripos) e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - 1; } else { p = ZSTR_VAL(haystack); - if (offset < -ZEND_LONG_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { + if (offset < -ZEND_LONG_MAX || ZEND_LONG_GT_SIZE_T(-offset, ZSTR_LEN(haystack))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -2161,7 +2161,7 @@ PHP_FUNCTION(strripos) haystack_dup = zend_string_tolower(haystack); if (offset >= 0) { - if ((size_t)offset > ZSTR_LEN(haystack)) { + if (ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(haystack))) { zend_string_release_ex(haystack_dup, 0); zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); @@ -2169,7 +2169,7 @@ PHP_FUNCTION(strripos) p = ZSTR_VAL(haystack_dup) + offset; e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack); } else { - if (offset < -ZEND_LONG_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { + if (offset < -ZEND_LONG_MAX || ZEND_LONG_GT_SIZE_T(-offset, ZSTR_LEN(haystack))) { zend_string_release_ex(haystack_dup, 0); zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); @@ -2274,9 +2274,11 @@ PHP_FUNCTION(chunk_split) Z_PARAM_STRING(end, endlen) ZEND_PARSE_PARAMETERS_END(); - if (chunklen <= 0) { + if (UNEXPECTED(chunklen <= 0)) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(chunklen)) { + chunklen = (zend_long) SIZE_MAX; } if ((size_t)chunklen > ZSTR_LEN(str)) { @@ -2304,12 +2306,11 @@ static inline void _zend_substr(zval *return_value, zend_string *str, zend_long /* if "from" position is negative, count start position from the end * of the string */ - if (-(size_t)f > ZSTR_LEN(str)) { + f = (zend_long)ZSTR_LEN(str) + f; + if (f < 0) { f = 0; - } else { - f = (zend_long)ZSTR_LEN(str) + f; } - } else if ((size_t)f > ZSTR_LEN(str)) { + } else if (ZEND_LONG_GT_SIZE_T(f, ZSTR_LEN(str))) { RETURN_EMPTY_STRING(); } @@ -2318,13 +2319,18 @@ static inline void _zend_substr(zval *return_value, zend_string *str, zend_long /* if "length" position is negative, set it to the length * needed to stop that many chars from the end of the string */ - if (-(size_t)l > ZSTR_LEN(str) - (size_t)f) { + l = (zend_long)ZSTR_LEN(str) - f + l; + if (l < 0) { l = 0; - } else { - l = (zend_long)ZSTR_LEN(str) - f + l; } - } else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) { - l = (zend_long)ZSTR_LEN(str) - f; + } else { + if (ZEND_LONG_SIZE_T_OVFL(l)) { + l = SIZE_MAX; + } + + if ((size_t)l > ZSTR_LEN(str) - (size_t)f) { + l = (zend_long)ZSTR_LEN(str) - f; + } } } else { l = (zend_long)ZSTR_LEN(str) - f; @@ -2439,7 +2445,7 @@ PHP_FUNCTION(substr_replace) if (f < 0) { f = 0; } - } else if ((size_t)f > ZSTR_LEN(str)) { + } else if (ZEND_LONG_GT_SIZE_T(f, ZSTR_LEN(str))) { f = ZSTR_LEN(str); } /* if "length" position is negative, set it to the length @@ -2452,7 +2458,7 @@ PHP_FUNCTION(substr_replace) } } - if ((size_t)l > ZSTR_LEN(str)) { + if (ZEND_LONG_GT_SIZE_T(l, ZSTR_LEN(str))) { l = ZSTR_LEN(str); } @@ -2545,7 +2551,7 @@ PHP_FUNCTION(substr_replace) if (f < 0) { f = 0; } - } else if (f > (zend_long)ZSTR_LEN(orig_str)) { + } else if (ZEND_LONG_GT_SIZE_T(f, ZSTR_LEN(orig_str))) { f = ZSTR_LEN(orig_str); } from_idx++; @@ -2559,7 +2565,7 @@ PHP_FUNCTION(substr_replace) if (f < 0) { f = 0; } - } else if (f > (zend_long)ZSTR_LEN(orig_str)) { + } else if (ZEND_LONG_GT_SIZE_T(f, ZSTR_LEN(orig_str))) { f = ZSTR_LEN(orig_str); } } @@ -2603,7 +2609,7 @@ PHP_FUNCTION(substr_replace) ZEND_ASSERT(0 <= f && f <= ZEND_LONG_MAX); ZEND_ASSERT(0 <= l && l <= ZEND_LONG_MAX); - if (((size_t) f + l) > ZSTR_LEN(orig_str)) { + if (ZEND_ULONG_GT_SIZE_T((zend_ulong) f + (zend_ulong) l, ZSTR_LEN(orig_str))) { l = ZSTR_LEN(orig_str) - f; } @@ -5627,6 +5633,9 @@ PHP_FUNCTION(str_repeat) if (mult < 0) { zend_argument_value_error(2, "must be greater than or equal to 0"); RETURN_THROWS(); + } else if (ZEND_LONG_SIZE_T_OVFL(mult)) { + zend_argument_value_error(2, "must be less than or equal to %zu", SIZE_MAX); + RETURN_THROWS(); } /* Don't waste our time if it's empty */ @@ -5635,13 +5644,13 @@ PHP_FUNCTION(str_repeat) RETURN_EMPTY_STRING(); /* Initialize the result string */ - result = zend_string_safe_alloc(ZSTR_LEN(input_str), mult, 0, 0); - result_len = ZSTR_LEN(input_str) * mult; + result = zend_string_safe_alloc(ZSTR_LEN(input_str), (size_t) mult, 0, 0); + result_len = ZSTR_LEN(input_str) * (size_t) mult; ZSTR_COPY_CONCAT_PROPERTIES(result, input_str); /* Heavy optimization for situations where input string is 1 byte long */ if (ZSTR_LEN(input_str) == 1) { - memset(ZSTR_VAL(result), *ZSTR_VAL(input_str), mult); + memset(ZSTR_VAL(result), *ZSTR_VAL(input_str), (size_t) mult); } else { const char *s, *ee; char *e; @@ -5847,7 +5856,7 @@ PHP_FUNCTION(substr_count) if (offset < 0) { offset += (zend_long)haystack_len; } - if ((offset < 0) || ((size_t)offset > haystack_len)) { + if ((offset < 0) || ZEND_LONG_GT_SIZE_T(offset, haystack_len)) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -5859,7 +5868,7 @@ PHP_FUNCTION(substr_count) if (length < 0) { length += haystack_len; } - if (length < 0 || ((size_t)length > haystack_len)) { + if (length < 0 || ZEND_LONG_GT_SIZE_T(length, haystack_len)) { zend_argument_value_error(4, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } @@ -5926,6 +5935,11 @@ PHP_FUNCTION(str_pad) Z_PARAM_LONG(pad_type_val) ZEND_PARSE_PARAMETERS_END(); + if (ZEND_LONG_SIZE_T_OVFL(pad_length)) { + zend_argument_value_error(2, "must be less or equal to %zu", SIZE_MAX); + RETURN_THROWS(); + } + /* If resulting string turns out to be shorter than input string, we simply copy the input and return. */ if (pad_length < 0 || (size_t)pad_length <= ZSTR_LEN(input)) { @@ -6275,7 +6289,7 @@ PHP_FUNCTION(str_split) RETURN_THROWS(); } - if ((size_t)split_length >= ZSTR_LEN(str)) { + if (ZEND_LONG_GTE_SIZE_T(split_length, ZSTR_LEN(str))) { if (0 == ZSTR_LEN(str)) { RETURN_EMPTY_ARRAY(); } @@ -6366,21 +6380,30 @@ PHP_FUNCTION(substr_compare) } if (offset < 0) { - offset = ZSTR_LEN(s1) + offset; - offset = (offset < 0) ? 0 : offset; + if (offset < -((zend_long) ZSTR_LEN(s1))) { + offset = 0; + } else { + offset = ZSTR_LEN(s1) + offset; + } } - if ((size_t)offset > ZSTR_LEN(s1)) { + if (ZEND_LONG_GT_SIZE_T(offset, ZSTR_LEN(s1))) { zend_argument_value_error(3, "must be contained in argument #1 ($haystack)"); RETURN_THROWS(); } - cmp_len = len ? (size_t)len : MAX(ZSTR_LEN(s2), (ZSTR_LEN(s1) - offset)); + if (!len) { + cmp_len = MAX(ZSTR_LEN(s2), (ZSTR_LEN(s1) - (size_t) offset)); + } else if (ZEND_LONG_SIZE_T_OVFL(len)) { + cmp_len = SIZE_MAX; + } else { + cmp_len = (size_t) len; + } if (!cs) { - RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len)); + RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1) + (size_t) offset, ZSTR_LEN(s1) - (size_t) offset, ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len)); } else { - RETURN_LONG(zend_binary_strncasecmp_l(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len)); + RETURN_LONG(zend_binary_strncasecmp_l(ZSTR_VAL(s1) + (size_t) offset, ZSTR_LEN(s1) - (size_t) offset, ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len)); } } /* }}} */ diff --git a/ext/standard/tests/file/fgetcsv_length_sizet.phpt b/ext/standard/tests/file/fgetcsv_length_sizet.phpt new file mode 100644 index 000000000000..3ee97763f0e9 --- /dev/null +++ b/ext/standard/tests/file/fgetcsv_length_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +fgetcsv() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($f); +?> +--EXPECTF-- +fgetcsv(): Argument #2 ($length) must be between 0 and %d diff --git a/ext/standard/tests/file/fgets_length_sizet.phpt b/ext/standard/tests/file/fgets_length_sizet.phpt new file mode 100644 index 000000000000..1ea2f9efbe4f --- /dev/null +++ b/ext/standard/tests/file/fgets_length_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +fgets() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($f); +?> +--EXPECTF-- +fgets(): Argument #2 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/file/file_get_contents_length_sizet.phpt b/ext/standard/tests/file/file_get_contents_length_sizet.phpt new file mode 100644 index 000000000000..064135883fe4 --- /dev/null +++ b/ext/standard/tests/file/file_get_contents_length_sizet.phpt @@ -0,0 +1,19 @@ +--TEST-- +file_get_contents() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECTF-- +file_get_contents(): Argument #5 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/file/fread_length_sizet.phpt b/ext/standard/tests/file/fread_length_sizet.phpt new file mode 100644 index 000000000000..aa26838baddd --- /dev/null +++ b/ext/standard/tests/file/fread_length_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +fread() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($f); +?> +--EXPECTF-- +fread(): Argument #2 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/file/ftruncate_error_sizet.phpt b/ext/standard/tests/file/ftruncate_error_sizet.phpt new file mode 100644 index 000000000000..2cc252182f47 --- /dev/null +++ b/ext/standard/tests/file/ftruncate_error_sizet.phpt @@ -0,0 +1,51 @@ +--TEST-- +ftruncate() on memory streams rejects sizes that exceed ZSTR_MAX_LEN +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; + } + + try { + $f = fopen('php://memory', 'w+'); + var_dump(ftruncate($f, $size)); + } catch (ValueError $e) { + echo $e->getMessage(), "\n"; + } +} + +echo "done\n"; +?> +--EXPECTF-- +bool(false) +bool(false) +bool(false) +bool(false) +ftruncate(): Argument #2 ($size) must be less than or equal to %d +ftruncate(): Argument #2 ($size) must be less than or equal to %d +ftruncate(): Argument #2 ($size) must be less than or equal to %d +ftruncate(): Argument #2 ($size) must be less than or equal to %d +bool(false) +bool(false) + +Fatal error: Allowed memory size of %d bytes exhausted at %s (tried to allocate %d bytes) in %s on line %d diff --git a/ext/standard/tests/file/fwrite.phpt b/ext/standard/tests/file/fwrite.phpt index e29c6a3507de..7f284d8c21b6 100644 --- a/ext/standard/tests/file/fwrite.phpt +++ b/ext/standard/tests/file/fwrite.phpt @@ -14,7 +14,7 @@ var_dump(fwrite($fp, "data")); $fp = fopen($filename, "w"); var_dump(fwrite($fp, "data", -1)); -var_dump(fwrite($fp, "data", 100000)); +var_dump(fwrite($fp, "data", PHP_INT_MAX)); fclose($fp); var_dump(file_get_contents($filename)); diff --git a/ext/standard/tests/file/umask_variation1.phpt b/ext/standard/tests/file/umask_variation1.phpt index f5a5a26e5577..dbab7dd52fb7 100644 --- a/ext/standard/tests/file/umask_variation1.phpt +++ b/ext/standard/tests/file/umask_variation1.phpt @@ -8,7 +8,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { ?> --FILE-- --FILE-- --EXPECTF-- Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/ext/standard/tests/streams/stream_copy_to_stream_maxlength_sizet.phpt b/ext/standard/tests/streams/stream_copy_to_stream_maxlength_sizet.phpt new file mode 100644 index 000000000000..05ad051453cf --- /dev/null +++ b/ext/standard/tests/streams/stream_copy_to_stream_maxlength_sizet.phpt @@ -0,0 +1,25 @@ +--TEST-- +stream_copy_to_stream() $maxLength overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($src); +fclose($dst); +?> +--EXPECTF-- +stream_copy_to_stream(): Argument #3 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/streams/stream_get_contents_maxlength_sizet.phpt b/ext/standard/tests/streams/stream_get_contents_maxlength_sizet.phpt new file mode 100644 index 000000000000..2f5f0930a01e --- /dev/null +++ b/ext/standard/tests/streams/stream_get_contents_maxlength_sizet.phpt @@ -0,0 +1,23 @@ +--TEST-- +stream_get_contents() $maxLength overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($s); +?> +--EXPECTF-- +stream_get_contents(): Argument #2 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/streams/stream_get_line_length_sizet.phpt b/ext/standard/tests/streams/stream_get_line_length_sizet.phpt new file mode 100644 index 000000000000..5547ec6289aa --- /dev/null +++ b/ext/standard/tests/streams/stream_get_line_length_sizet.phpt @@ -0,0 +1,23 @@ +--TEST-- +stream_get_line() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($s); +?> +--EXPECTF-- +stream_get_line(): Argument #2 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/streams/stream_set_read_buffer_sizet.phpt b/ext/standard/tests/streams/stream_set_read_buffer_sizet.phpt new file mode 100644 index 000000000000..ae18e9179cd4 --- /dev/null +++ b/ext/standard/tests/streams/stream_set_read_buffer_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +stream_set_read_buffer() $size overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($s); +?> +--EXPECTF-- +stream_set_read_buffer(): Argument #2 ($size) must be less than or equal to %d diff --git a/ext/standard/tests/streams/stream_set_write_buffer_sizet.phpt b/ext/standard/tests/streams/stream_set_write_buffer_sizet.phpt new file mode 100644 index 000000000000..a5556f57778b --- /dev/null +++ b/ext/standard/tests/streams/stream_set_write_buffer_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +stream_set_write_buffer() $size overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($s); +?> +--EXPECTF-- +stream_set_write_buffer(): Argument #2 ($size) must be less than or equal to %d diff --git a/ext/standard/tests/streams/stream_socket_recvfrom_length_sizet.phpt b/ext/standard/tests/streams/stream_socket_recvfrom_length_sizet.phpt new file mode 100644 index 000000000000..d3dcc51ec728 --- /dev/null +++ b/ext/standard/tests/streams/stream_socket_recvfrom_length_sizet.phpt @@ -0,0 +1,21 @@ +--TEST-- +stream_socket_recvfrom() $length overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +fclose($sock); +?> +--EXPECTF-- +stream_socket_recvfrom(): Argument #2 ($length) must be less than or equal to %d diff --git a/ext/standard/tests/strings/bug72146.phpt b/ext/standard/tests/strings/bug72146.phpt index 72b332570ff2..3802bc2122b9 100644 --- a/ext/standard/tests/strings/bug72146.phpt +++ b/ext/standard/tests/strings/bug72146.phpt @@ -1,8 +1,8 @@ --TEST-- Bug #72146 (Integer overflow on substr_replace) --FILE-- - --EXPECT-- array(1) { diff --git a/ext/standard/tests/strings/chunk_split_variation8.phpt b/ext/standard/tests/strings/chunk_split_variation8.phpt index b0c889494e40..9d07a6a843c6 100644 --- a/ext/standard/tests/strings/chunk_split_variation8.phpt +++ b/ext/standard/tests/strings/chunk_split_variation8.phpt @@ -33,7 +33,7 @@ $values = array ( PHP_INT_MAX, // max positive integer number PHP_INT_MAX * 3, // integer overflow -PHP_INT_MAX - 1, // min negative integer - + (2 ** (PHP_SYS_SIZE * 8 - 2) - 1 << 1) + 1, // SSIZE_MAX ); @@ -80,3 +80,8 @@ chunk_split():::" chunk_split(): Argument #2 ($length) must be of type int, float given -- Iteration 8 -- chunk_split(): Argument #2 ($length) must be greater than 0 +-- Iteration 9 -- +string(129) "This's heredoc string with and + white space char. +It has _speci@l ch@r$ 2222 !!!Now \k as escape char to test +chunk_split():::" diff --git a/ext/standard/tests/strings/gh15613.phpt b/ext/standard/tests/strings/gh15613.phpt index 44c41acfddd1..20ff1620ee81 100644 --- a/ext/standard/tests/strings/gh15613.phpt +++ b/ext/standard/tests/strings/gh15613.phpt @@ -3,7 +3,7 @@ GH-15613 overflow on hex strings repeater value --SKIPIF-- --INI-- memory_limit=-1 diff --git a/ext/standard/tests/strings/metaphone_max_phonemes_sizet.phpt b/ext/standard/tests/strings/metaphone_max_phonemes_sizet.phpt new file mode 100644 index 000000000000..ad93bf52de48 --- /dev/null +++ b/ext/standard/tests/strings/metaphone_max_phonemes_sizet.phpt @@ -0,0 +1,20 @@ +--TEST-- +metaphone() $maxPhonemes overflow on narrow size_t +--SKIPIF-- += PHP_INT_SIZE) { + die("skip size_t is not narrower than zend_long on this platform"); +} +?> +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECTF-- +Deprecated: Function metaphone() is deprecated since 8.6, use a userland phonetic matching library instead in %s on line %d +metaphone(): Argument #2 ($max_phonemes) must be less than or equal to %d diff --git a/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt b/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt index 27837e518a71..1e46a6570f77 100644 --- a/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt +++ b/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt @@ -7,22 +7,24 @@ gmp $a = new GMP("42"); $b = new GMP("-1337"); -$c = new GMP("999999999999999999999999999999999"); +$c = new GMP((string)PHP_INT_MAX); +$d = new GMP((string)PHP_INT_MIN); +$e = new GMP("999999999999999999999999999999999"); try { if (PHP_INT_SIZE == 8) { - var_dump(sprintf("%d/%d/%d/%s", $a, $b, $c, $c + 1)); - var_dump("42/-1337/2147483647/1000000000000000000000000000000000"); + var_dump(sprintf("%d/%d/%d/%d/%d/%s", $a, $b, $c, $d, $e, $e + 1)); + var_dump("42/-1337/2147483647/-2147483648/2147483647/1000000000000000000000000000000000"); } else { - var_dump("42/-1337/4089650035136921599/1000000000000000000000000000000000"); - var_dump(sprintf("%d/%d/%d/%s", $a, $b, $c, $c + 1)); + var_dump("42/-1337/9223372036854775807/-9223372036854775808/4089650035136921599/1000000000000000000000000000000000"); + var_dump(sprintf("%d/%d/%d/%d/%d/%s", $a, $b, $c, $d, $e, $e + 1)); } } catch (\Throwable $e) {echo $e, PHP_EOL; } echo PHP_EOL; echo "Done"; ?> --EXPECTF-- -string(63) "42/-1337/4089650035136921599/1000000000000000000000000000000000" -string(54) "42/-1337/2147483647/1000000000000000000000000000000000" +string(104) "42/-1337/9223372036854775807/-9223372036854775808/4089650035136921599/1000000000000000000000000000000000" +string(77) "42/-1337/2147483647/-2147483648/2147483647/1000000000000000000000000000000000" Done diff --git a/ext/standard/tests/strings/str_pad_variation1.phpt b/ext/standard/tests/strings/str_pad_variation1.phpt index cb71e61156fc..11471e58a46a 100644 --- a/ext/standard/tests/strings/str_pad_variation1.phpt +++ b/ext/standard/tests/strings/str_pad_variation1.phpt @@ -1,5 +1,7 @@ --TEST-- Test str_pad() function : usage variations - large values for '$pad_length' argument +--INI-- +memory_limit=1g --SKIPIF-- getMessage() . "\n"; } -$php_int_max_pad_length = PHP_INT_MAX; -var_dump( str_pad($input, $php_int_max_pad_length) ); - +// INT32_MAX +var_dump( str_pad($input, 2147483647) ); ?> --EXPECTF-- -*** Testing str_pad() function: with large value for for 'pad_length' argument *** +*** Testing str_pad() function: with large value for 'pad_length' argument *** str_pad(): Argument #2 ($length) must be of type int, float given Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/ext/standard/tests/strings/str_pad_variation2.phpt b/ext/standard/tests/strings/str_pad_variation2.phpt index 0bf8ad3ad80a..6377113a0e64 100644 --- a/ext/standard/tests/strings/str_pad_variation2.phpt +++ b/ext/standard/tests/strings/str_pad_variation2.phpt @@ -10,7 +10,7 @@ $string = chr(0).chr(255).chr(128).chr(234).chr(143); /* different pad_lengths */ $pad_lengths = [ - -PHP_INT_MAX, // huge negative value + (-2 ** (PHP_SYS_SIZE * 8 - 2)) << 1, // huge negative value -1, // negative value 0, // pad_length < sizeof(input_string) 9, // pad_length <= sizeof(input_string) diff --git a/ext/standard/tests/strings/str_pad_variation5.phpt b/ext/standard/tests/strings/str_pad_variation5.phpt index 1a65366c823c..6017b1766125 100644 --- a/ext/standard/tests/strings/str_pad_variation5.phpt +++ b/ext/standard/tests/strings/str_pad_variation5.phpt @@ -4,26 +4,26 @@ Test str_pad() function : usage variations - unexpected large value for '$pad_le memory_limit=128M --SKIPIF-- = PHP_INT_SIZE) { + die("skip this test is for PHP_SYS_SIZE < PHP_INT_SIZE only"); +} if (getenv("USE_ZEND_ALLOC") === "0") { die("skip Zend MM disabled"); } -?> + --FILE-- getMessage()}\n"; +} -//defining '$input' argument -$input = "Test string"; -$pad_length = PHP_INT_MAX - 16; /* zend_string header is 16 bytes */ -var_dump( str_pad($input, $pad_length) ); +var_dump( str_pad($input, (2 ** (PHP_SYS_SIZE * 8-2) - 1 << 1) + 1) ); -?> --EXPECTF-- -*** Testing str_pad() function: with large value for for 'pad_length' argument *** +ValueError: str_pad(): Argument #2 ($length) must be less or equal to %d Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/ext/standard/tests/strings/str_repeat_sizet.phpt b/ext/standard/tests/strings/str_repeat_sizet.phpt new file mode 100644 index 000000000000..e3d42a917675 --- /dev/null +++ b/ext/standard/tests/strings/str_repeat_sizet.phpt @@ -0,0 +1,47 @@ +--TEST-- +str_repeat(): $times must fit into size_t when zend_long is wider +--SKIPIF-- += PHP_INT_SIZE) { + die("skip this test is for PHP_SYS_SIZE < PHP_INT_SIZE only"); +} +?> +--FILE-- +getMessage(), "\n"; + } +} + +echo "-- negative still reports the plain message --\n"; +try { + var_dump(str_repeat('12', -1)); +} catch (ValueError $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} + +echo "-- small enough to be a valid size_t: not rejected, allocation decides --\n"; +var_dump(str_repeat('1', $sizeMax)); +?> +--EXPECTF-- +-- wider than size_t: rejected before narrowing -- +ValueError: str_repeat(): Argument #2 ($times) must be less than or equal to %d +ValueError: str_repeat(): Argument #2 ($times) must be less than or equal to %d +ValueError: str_repeat(): Argument #2 ($times) must be less than or equal to %d +-- negative still reports the plain message -- +ValueError: str_repeat(): Argument #2 ($times) must be greater than or equal to 0 +-- small enough to be a valid size_t: not rejected, allocation decides -- + +Fatal error: Possible integer overflow in memory allocation (%s) in %s on line %d diff --git a/ext/standard/tests/strings/str_split_variation6.phpt b/ext/standard/tests/strings/str_split_variation6.phpt index a8c1bbf1a927..706f5033ef76 100644 --- a/ext/standard/tests/strings/str_split_variation6.phpt +++ b/ext/standard/tests/strings/str_split_variation6.phpt @@ -19,6 +19,8 @@ $values = array ( 0x1A, //hexadecimal number 2147483647, //max positive integer number -2147483648, //min negative integer + PHP_INT_MAX, + (2 ** (PHP_SYS_SIZE * 8 - 2) - 1 << 1) + 1, // SSIZE_MAX ); //loop through each element of $values for 'split_length' @@ -144,3 +146,13 @@ array(1) { } -- Iteration 7 -- str_split(): Argument #2 ($length) must be greater than 0 +-- Iteration 8 -- +array(1) { + [0]=> + string(42) "This is a string with 123 & escape char \t" +} +-- Iteration 9 -- +array(1) { + [0]=> + string(42) "This is a string with 123 & escape char \t" +} diff --git a/ext/standard/tests/strings/stripos_error.phpt b/ext/standard/tests/strings/stripos_error.phpt index a3e805a709f9..ce1ab1ee085e 100644 --- a/ext/standard/tests/strings/stripos_error.phpt +++ b/ext/standard/tests/strings/stripos_error.phpt @@ -11,6 +11,12 @@ try { echo $exception->getMessage() . "\n"; } +try { + stripos("Hello World", "o", PHP_INT_MAX); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + echo "\n-- Offset before the start of the string --\n"; try { stripos("Hello World", "o", -12); @@ -18,6 +24,12 @@ try { echo $exception->getMessage() . "\n"; } +try { + stripos("Hello World", "o", PHP_INT_MIN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + echo "*** Done ***"; ?> --EXPECT-- @@ -25,7 +37,9 @@ echo "*** Done ***"; -- Offset beyond the end of the string -- stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) -- Offset before the start of the string -- stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) *** Done *** diff --git a/ext/standard/tests/strings/strpos_error.phpt b/ext/standard/tests/strings/strpos_error.phpt new file mode 100644 index 000000000000..d37344da68a3 --- /dev/null +++ b/ext/standard/tests/strings/strpos_error.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test strpos() function : error conditions +--FILE-- +getMessage() . "\n"; +} + +try { + strpos("Hello World", "o", PHP_INT_MAX); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "\n-- Offset before the start of the string --\n"; +try { + strpos("Hello World", "o", -12); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + strpos("Hello World", "o", PHP_INT_MIN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "*** Done ***"; +?> +--EXPECT-- +*** Testing strpos() function: error conditions *** + +-- Offset beyond the end of the string -- +strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) + +-- Offset before the start of the string -- +strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +*** Done *** diff --git a/ext/standard/tests/strings/strripos_error.phpt b/ext/standard/tests/strings/strripos_error.phpt new file mode 100644 index 000000000000..4dccc461cfbb --- /dev/null +++ b/ext/standard/tests/strings/strripos_error.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test strripos() function : error conditions +--FILE-- +getMessage() . "\n"; +} + +try { + strripos("Hello World", "o", PHP_INT_MAX); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "\n-- Offset before the start of the string --\n"; +try { + strripos("Hello World", "o", -12); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + strripos("Hello World", "o", PHP_INT_MIN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "*** Done ***"; +?> +--EXPECT-- +*** Testing strripos() function: error conditions *** + +-- Offset beyond the end of the string -- +strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) + +-- Offset before the start of the string -- +strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +*** Done *** diff --git a/ext/standard/tests/strings/strrpos_error.phpt b/ext/standard/tests/strings/strrpos_error.phpt new file mode 100644 index 000000000000..85206eddfd7f --- /dev/null +++ b/ext/standard/tests/strings/strrpos_error.phpt @@ -0,0 +1,45 @@ +--TEST-- +Test strrpos() function : error conditions +--FILE-- +getMessage() . "\n"; +} + +try { + strrpos("Hello World", "o", PHP_INT_MAX); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "\n-- Offset before the start of the string --\n"; +try { + strrpos("Hello World", "o", -12); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + strrpos("Hello World", "o", PHP_INT_MIN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "*** Done ***"; +?> +--EXPECT-- +*** Testing strrpos() function: error conditions *** + +-- Offset beyond the end of the string -- +strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) + +-- Offset before the start of the string -- +strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +*** Done *** diff --git a/ext/standard/tests/strings/substr.phpt b/ext/standard/tests/strings/substr.phpt index c870e1de0fbd..d3fb68e64bef 100644 --- a/ext/standard/tests/strings/substr.phpt +++ b/ext/standard/tests/strings/substr.phpt @@ -59,6 +59,16 @@ echo "\n*** Omitting length or using NULL length ***\n"; var_dump (substr("abcdef" , 2) ); var_dump (substr("abcdef" , 2, NULL) ); +/* Very big offset */ +echo "\n*** Very big offset ***\n"; +var_dump (substr("abcdef" , PHP_INT_MAX) ); +var_dump (substr("abcdef" , PHP_INT_MIN) ); + +/* Very big length */ +echo "\n*** Very big length ***\n"; +var_dump (substr("abcdef" , 0, PHP_INT_MAX) ); +var_dump (substr("abcdef" , 0, PHP_INT_MIN) ); + echo"\nDone"; ?> @@ -173,4 +183,12 @@ string(4) "abcd" string(4) "cdef" string(4) "cdef" +*** Very big offset *** +string(0) "" +string(6) "abcdef" + +*** Very big length *** +string(6) "abcdef" +string(0) "" + Done diff --git a/ext/standard/tests/strings/substr_compare.phpt b/ext/standard/tests/strings/substr_compare.phpt index 51d093a65fa2..995588940f42 100644 --- a/ext/standard/tests/strings/substr_compare.phpt +++ b/ext/standard/tests/strings/substr_compare.phpt @@ -13,13 +13,25 @@ var_dump(substr_compare("abcde", "cd", 1, 2) < 0); var_dump(substr_compare("abcde", "abc", 5, 1)); var_dump(substr_compare("abcde", "abcdef", -10, 10) < 0); var_dump(substr_compare("abcde", "abc", 0, 0)); +var_dump(substr_compare("abc", "abcde", 0, PHP_INT_MAX)); echo "Test\n"; +var_dump(substr_compare("abcde", "abc", 0)); +var_dump(substr_compare("abcde", "abc", -100)); +var_dump(substr_compare("abcde", "abc", -PHP_INT_MAX)); + try { - substr_compare("abcde", "abc", 0, -1); + var_dump(substr_compare("abcde", "abc", 0, -1)); } catch (\ValueError $e) { echo $e->getMessage() . "\n"; } + +try { + var_dump(substr_compare("abcde", "abc", 0, PHP_INT_MIN)); +} catch (\ValueError $e) { + echo $e->getMessage() . "\n"; +} + var_dump(substr_compare("abcde", "abc", -1, NULL, -5) > 0); ?> --EXPECT-- @@ -33,6 +45,11 @@ bool(true) int(-1) bool(true) int(0) +int(-1) Test +int(1) +int(1) +int(1) +substr_compare(): Argument #4 ($length) must be greater than or equal to 0 substr_compare(): Argument #4 ($length) must be greater than or equal to 0 bool(true) diff --git a/ext/standard/tests/strings/substr_count_error.phpt b/ext/standard/tests/strings/substr_count_error.phpt index dc0d3d9834eb..614547577eec 100644 --- a/ext/standard/tests/strings/substr_count_error.phpt +++ b/ext/standard/tests/strings/substr_count_error.phpt @@ -20,6 +20,21 @@ try { echo $exception->getMessage() . "\n"; } +/* offset very big */ +try { + substr_count($str, 'b', PHP_INT_MAX); + echo "unexpected success\n"; +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +try { + substr_count($str, 'b', PHP_INT_MIN); + echo "unexpected success\n"; +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + /* Using offset and length to go beyond the size of the string: Exception is expected, as length+offset > length of string */ try { @@ -35,6 +50,21 @@ try { echo $exception->getMessage() . "\n"; } +/* length very big */ +try { + substr_count($str, 'b', 0, PHP_INT_MAX); + echo "unexpected success\n"; +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +try { + substr_count($str, 'b', 0, PHP_INT_MIN); + echo "unexpected success\n"; +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + echo "Done\n"; ?> @@ -42,6 +72,10 @@ echo "Done\n"; *** Testing error conditions *** substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack) +substr_count(): Argument #4 ($length) must be contained in argument #1 ($haystack) +substr_count(): Argument #4 ($length) must be contained in argument #1 ($haystack) substr_count(): Argument #4 ($length) must be contained in argument #1 ($haystack) substr_count(): Argument #4 ($length) must be contained in argument #1 ($haystack) Done diff --git a/ext/standard/tests/strings/substr_replace_large_offset_length.phpt b/ext/standard/tests/strings/substr_replace_large_offset_length.phpt new file mode 100644 index 000000000000..c6cb329d1218 --- /dev/null +++ b/ext/standard/tests/strings/substr_replace_large_offset_length.phpt @@ -0,0 +1,39 @@ +--TEST-- +Test substr_replace() function : large offset & length +--FILE-- +getMessage(), "\n"; +} + +try { + var_dump(substr_replace('hello', 'X', PHP_INT_MIN)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +echo "*** Very large length ***\n"; +try { + var_dump(substr_replace('hello', 'X', 0, PHP_INT_MAX)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(substr_replace('hello', 'X', 0, PHP_INT_MIN)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +*** Very large offset *** +string(6) "helloX" +string(1) "X" +*** Very large length *** +string(1) "X" +string(6) "Xhello" diff --git a/main/streams/memory.c b/main/streams/memory.c index e76598ed0f46..ad3877f1e1b2 100644 --- a/main/streams/memory.c +++ b/main/streams/memory.c @@ -243,6 +243,8 @@ static int php_stream_memory_set_option(php_stream *stream, int option, int valu if (newsize < ms->fpos) { ms->fpos = newsize; } + } else if (UNEXPECTED(newsize > ZSTR_MAX_LEN)) { + return PHP_STREAM_OPTION_RETURN_ERR; } else { size_t old_size = ZSTR_LEN(ms->data); ms->data = zend_string_realloc(ms->data, newsize, 0); From bbb116395014e25408863685ec8a6588044aea15 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:36:51 +0200 Subject: [PATCH 07/12] Fix ext/date --- ext/date/php_date.c | 21 ++++++++++++++++----- ext/date/php_date.h | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 27664623c6b9..11c9ee64fe09 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -669,6 +669,18 @@ static const char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib } /* }}} */ +static zend_long date_date_to_zlong(timelib_time *d, int *error) +{ +#if SIZEOF_ZEND_LONG >= SIZEOF_LONG_LONG + if (error) { + *error = 0; + } + return (zend_long) d->sse; +#else + return timelib_date_to_int(d, error); +#endif +} + /* {{{ date_format - (gm)date helper */ static zend_string *date_format(const char *format, size_t format_len, const timelib_time *t, bool localtime) { @@ -882,7 +894,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, bool localtime) } /* }}} */ -PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_t ts, bool localtime) /* {{{ */ +PHPAPI zend_string *php_format_date(const char *format, size_t format_len, zend_long ts, bool localtime) /* {{{ */ { timelib_time *t; timelib_tzinfo *tzi; @@ -1136,7 +1148,7 @@ PHP_FUNCTION(strtotime) timelib_fill_holes(t, now, TIMELIB_NO_CLONE); timelib_update_ts(t, tzi); - ts = timelib_date_to_int(t, &epoch_does_not_fit_in_zend_long); + ts = date_date_to_zlong(t, &epoch_does_not_fit_in_zend_long); timelib_time_dtor(now); timelib_time_dtor(t); @@ -1219,8 +1231,7 @@ PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, bool gmt) } /* Clean up and return */ - ts = timelib_date_to_int(now, &epoch_does_not_fit_in_zend_long); - + ts = date_date_to_zlong(now, &epoch_does_not_fit_in_zend_long); if (epoch_does_not_fit_in_zend_long) { timelib_time_dtor(now); php_error_docref(NULL, E_WARNING, "Epoch doesn't fit in a PHP integer"); @@ -3969,7 +3980,7 @@ PHP_FUNCTION(date_timestamp_get) timelib_update_ts(dateobj->time, NULL); } - timestamp = timelib_date_to_int(dateobj->time, &epoch_does_not_fit_in_zend_long); + timestamp = date_date_to_zlong(dateobj->time, &epoch_does_not_fit_in_zend_long); if (epoch_does_not_fit_in_zend_long) { zend_throw_error(date_ce_date_range_error, "Epoch doesn't fit in a PHP integer"); diff --git a/ext/date/php_date.h b/ext/date/php_date.h index 97a49974f1a4..ac2950a5ab85 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -132,7 +132,7 @@ PHPAPI bool php_idate(char format, time_t ts, bool localtime, int *result); #define _php_strftime php_strftime PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, bool gm); -PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_t ts, bool localtime); +PHPAPI zend_string *php_format_date(const char *format, size_t format_len, zend_long ts, bool localtime); PHPAPI zend_string *php_format_date_obj(const char *format, size_t format_len, const php_date_obj *date_obj); /* Mechanism to set new TZ database */ From c32f3c2c08799dd8063386a87b7557044725e8f6 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:38:26 +0200 Subject: [PATCH 08/12] Fix ext/socket --- ext/sockets/sendrecvmsg.c | 2 ++ ext/zend_test/test.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index cc268bd68b0a..64f9738738db 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -314,7 +314,9 @@ PHP_FUNCTION(socket_cmsg_space) size_t size = entry->size + n * entry->var_el_size; size_t total_size = CMSG_SPACE(size); if (n > n_max /* zend_long overflow */ +#if SIZEOF_SIZE_T >= SIZEOF_ZEND_LONG || total_size > ZEND_LONG_MAX +#endif || total_size < size /* align overflow */) { zend_argument_value_error(3, "is too large"); RETURN_THROWS(); diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 82bfa8d38e33..13f1b0f9c3a3 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -1608,7 +1608,7 @@ static ZEND_FUNCTION(zend_test_is_zend_ptr) Z_PARAM_LONG(addr); ZEND_PARSE_PARAMETERS_END(); - RETURN_BOOL(is_zend_ptr((void*)addr)); + RETURN_BOOL(is_zend_ptr((void*)(intptr_t)addr)); } static ZEND_FUNCTION(zend_test_log_err_debug) From a41f5cc9da90aef06a1477fb2f6d70650e6d9158 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:39:43 +0200 Subject: [PATCH 09/12] Fix ext/gmp --- ext/gmp/gmp.c | 139 +++++++++++++++++++++++++---- ext/gmp/tests/construct_32bit.phpt | 36 ++++++++ ext/gmp/tests/construct_64bit.phpt | 36 ++++++++ ext/gmp/tests/gmp_clrbit.phpt | 4 +- ext/gmp/tests/gmp_popcount.phpt | 1 - ext/gmp/tests/gmp_scan0.phpt | 2 +- ext/gmp/tests/gmp_scan1.phpt | 2 +- ext/gmp/tests/gmp_setbit.phpt | 2 +- ext/gmp/tests/gmp_setbit_long.phpt | 5 +- ext/gmp/tests/gmp_testbit.phpt | 4 +- 10 files changed, 204 insertions(+), 27 deletions(-) create mode 100644 ext/gmp/tests/construct_32bit.phpt create mode 100644 ext/gmp/tests/construct_64bit.phpt diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 4a81026d451b..4a2389020d35 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -104,6 +104,69 @@ PHP_GMP_API zend_class_entry *php_gmp_class_entry(void) { #define GET_GMP_FROM_ZVAL(zval) \ GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zval))->num +#define GMP_SI_MAX (GMP_NUMB_MAX >> 1) +#define GMP_SI_MIN (-(1LL << (GMP_NUMB_BITS - 1))) +#if GMP_NUMB_BITS < SIZEOF_ZEND_LONG*8 +static void gmp_set_zlong(mpz_t z, zend_long zlong) { + if (zlong <= GMP_SI_MAX && zlong >= GMP_SI_MIN) { + mpz_set_si(z, zlong); + } else if (zlong >= 0) { + mpz_import(z, 1, 1, sizeof(zend_long), 0, 0, &zlong); + } else { + mpz_import(z, 1, 1, sizeof(zend_long), 0, 0, &zlong); + mpz_neg(z, z); + } +} + +static int gmp_fits_zlong_p(mpz_t z) { + int result = 1; + mpz_t z_min_max; + zend_long min_max; + + if (mpz_cmp_si(z, GMP_SI_MAX) > 0) { + min_max = ZEND_LONG_MAX; + mpz_init(z_min_max); + mpz_import(z_min_max, 1, 1, sizeof(zend_long), 0, 0, &min_max); + result = mpz_cmp(z, z_min_max) <= 0; + mpz_clear(z_min_max); + } else if (mpz_cmp_si(z, GMP_SI_MIN) < 0) { + min_max = ZEND_LONG_MIN; + mpz_init(z_min_max); + mpz_import(z_min_max, 1, 1, sizeof(zend_long), 0, 0, &min_max); + mpz_neg(z_min_max, z_min_max); + result = mpz_cmp(z, z_min_max) >= 0; + mpz_clear(z_min_max); + } + + return result; +} + +static zend_long gmp_get_zlong(mpz_t z) { + zend_long result; + zend_long mask = -1; + mpz_t z_tmp; + mpz_t z_mask; + + if (mpz_cmp_si(z, GMP_SI_MAX) > 0 || mpz_cmp_si(z, GMP_SI_MIN) < 0) { + mpz_init(z_tmp); + mpz_init(z_mask); + mpz_import(z_mask, 1, 1, sizeof(zend_long), 0, 0, &mask); + mpz_and(z_tmp, z, z_mask); + mpz_export(&result, NULL, 0, sizeof(zend_long), 0, 0, z_tmp); + mpz_clear(z_mask); + mpz_clear(z_tmp); + } else { + result = mpz_get_si(z); + } + + return result; +} +#else +# define gmp_set_zlong(z, l) mpz_set_si(z, l) +# define gmp_fits_zlong_p(z) mpz_fits_si_p(z) +# define gmp_get_zlong(z) mpz_get_si(z) +#endif + static void gmp_strval(zval *result, mpz_t gmpnum, int base); static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos); @@ -127,7 +190,7 @@ static bool gmp_zend_parse_arg_into_mpz_ex( } if (Z_TYPE_P(arg) == IS_LONG) { - mpz_set_si(*destination_mpz_ptr, Z_LVAL_P(arg)); + gmp_set_zlong(*destination_mpz_ptr, Z_LVAL_P(arg)); return true; } @@ -143,7 +206,7 @@ static bool gmp_zend_parse_arg_into_mpz_ex( return false; } - mpz_set_si(*destination_mpz_ptr, lval); + gmp_set_zlong(*destination_mpz_ptr, lval); return true; } @@ -241,7 +304,7 @@ static zend_result gmp_cast_object(zend_object *readobj, zval *writeobj, int typ return SUCCESS; case IS_LONG: gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; - ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); + ZVAL_LONG(writeobj, gmp_get_zlong(gmpnum)); return SUCCESS; case IS_DOUBLE: gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; @@ -249,8 +312,8 @@ static zend_result gmp_cast_object(zend_object *readobj, zval *writeobj, int typ return SUCCESS; case _IS_NUMBER: gmpnum = GET_GMP_OBJECT_FROM_OBJ(readobj)->num; - if (mpz_fits_si_p(gmpnum)) { - ZVAL_LONG(writeobj, mpz_get_si(gmpnum)); + if (gmp_fits_zlong_p(gmpnum)) { + ZVAL_LONG(writeobj, gmp_get_zlong(gmpnum)); } else { ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum)); } @@ -732,7 +795,7 @@ static zend_result gmp_initialize_number(mpz_ptr gmp_number, const zend_string * return convert_zstr_to_gmp(gmp_number, arg_str, base, 1); } - mpz_set_si(gmp_number, arg_l); + gmp_set_zlong(gmp_number, arg_l); return SUCCESS; } @@ -882,7 +945,7 @@ ZEND_FUNCTION(gmp_intval) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum) ZEND_PARSE_PARAMETERS_END(); - RETVAL_LONG(mpz_get_si(gmpnum)); + RETVAL_LONG(gmp_get_zlong(gmpnum)); } /* }}} */ @@ -1610,8 +1673,13 @@ ZEND_FUNCTION(gmp_random_range) } /* }}} */ +#if SIZEOF_SIZE_T >= SIZEOF_ZEND_LONG +# define GMP_SAFE_BITINDEX_MAX ((mp_bitcnt_t)INT_MAX * GMP_NUMB_BITS) +#else +# define GMP_SAFE_BITINDEX_MAX ((mp_bitcnt_t)INT_MAX * GMP_NUMB_BITS - 1) +#endif static bool gmp_is_bit_index_valid(zend_long index) { - return index >= 0 && (index / GMP_NUMB_BITS < INT_MAX); + return index >= 0 && (zend_ulong)index <= GMP_SAFE_BITINDEX_MAX; } /* {{{ Sets or clear bit in a */ @@ -1627,7 +1695,7 @@ ZEND_FUNCTION(gmp_setbit) } if (!gmp_is_bit_index_valid(index)) { - zend_argument_value_error(2, "must be between 0 and %d * %d", INT_MAX, GMP_NUMB_BITS); + zend_argument_value_error(2, "must be between 0 and %lu", GMP_SAFE_BITINDEX_MAX); RETURN_THROWS(); } @@ -1653,7 +1721,7 @@ ZEND_FUNCTION(gmp_clrbit) } if (!gmp_is_bit_index_valid(index)) { - zend_argument_value_error(2, "must be between 0 and %d * %d", INT_MAX, GMP_NUMB_BITS); + zend_argument_value_error(2, "must be between 0 and %lu", GMP_SAFE_BITINDEX_MAX); RETURN_THROWS(); } @@ -1674,7 +1742,7 @@ ZEND_FUNCTION(gmp_testbit) ZEND_PARSE_PARAMETERS_END(); if (!gmp_is_bit_index_valid(index)) { - zend_argument_value_error(2, "must be between 0 and %d * %d", INT_MAX, GMP_NUMB_BITS); + zend_argument_value_error(2, "must be between 0 and %lu", GMP_SAFE_BITINDEX_MAX); RETURN_THROWS(); } @@ -1686,12 +1754,21 @@ ZEND_FUNCTION(gmp_testbit) ZEND_FUNCTION(gmp_popcount) { mpz_ptr gmpnum_a; + mp_bitcnt_t result; ZEND_PARSE_PARAMETERS_START(1, 1) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_a) ZEND_PARSE_PARAMETERS_END(); - RETURN_LONG(mpz_popcount(gmpnum_a)); + result = mpz_popcount(gmpnum_a); + +#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG + if (SIZE_MAX == result) { + RETURN_LONG(-1); + } +#endif + + RETURN_LONG(result); } /* }}} */ @@ -1699,13 +1776,22 @@ ZEND_FUNCTION(gmp_popcount) ZEND_FUNCTION(gmp_hamdist) { mpz_ptr gmpnum_a, gmpnum_b; + mp_bitcnt_t result; ZEND_PARSE_PARAMETERS_START(2, 2) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_a) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_b) ZEND_PARSE_PARAMETERS_END(); - RETURN_LONG(mpz_hamdist(gmpnum_a, gmpnum_b)); + result = mpz_hamdist(gmpnum_a, gmpnum_b); + +#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG + if (SIZE_MAX == result) { + RETURN_LONG(-1); + } +#endif + + RETURN_LONG(result); } /* }}} */ @@ -1714,6 +1800,7 @@ ZEND_FUNCTION(gmp_scan0) { mpz_ptr gmpnum_a; zend_long start; + mp_bitcnt_t result; ZEND_PARSE_PARAMETERS_START(2, 2) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_a) @@ -1721,11 +1808,19 @@ ZEND_FUNCTION(gmp_scan0) ZEND_PARSE_PARAMETERS_END(); if (!gmp_is_bit_index_valid(start)) { - zend_argument_value_error(2, "must be between 0 and %d * %d", INT_MAX, GMP_NUMB_BITS); + zend_argument_value_error(2, "must be between 0 and %lu", GMP_SAFE_BITINDEX_MAX); RETURN_THROWS(); } - RETURN_LONG(mpz_scan0(gmpnum_a, start)); + result = mpz_scan0(gmpnum_a, start); + +#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG + if (SIZE_MAX == result) { + RETURN_LONG(-1); + } +#endif + + RETURN_LONG(result); } /* }}} */ @@ -1734,6 +1829,8 @@ ZEND_FUNCTION(gmp_scan1) { mpz_ptr gmpnum_a; zend_long start; + mp_bitcnt_t result; + ZEND_PARSE_PARAMETERS_START(2, 2) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_a) @@ -1741,11 +1838,19 @@ ZEND_FUNCTION(gmp_scan1) ZEND_PARSE_PARAMETERS_END(); if (!gmp_is_bit_index_valid(start)) { - zend_argument_value_error(2, "must be between 0 and %d * %d", INT_MAX, GMP_NUMB_BITS); + zend_argument_value_error(2, "must be between 0 and %lu", GMP_SAFE_BITINDEX_MAX); RETURN_THROWS(); } - RETURN_LONG(mpz_scan1(gmpnum_a, start)); + result = mpz_scan1(gmpnum_a, start); + +#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG + if (SIZE_MAX == result) { + RETURN_LONG(-1); + } +#endif + + RETURN_LONG(result); } /* }}} */ diff --git a/ext/gmp/tests/construct_32bit.phpt b/ext/gmp/tests/construct_32bit.phpt new file mode 100644 index 000000000000..581d1d5b3eba --- /dev/null +++ b/ext/gmp/tests/construct_32bit.phpt @@ -0,0 +1,36 @@ +--TEST-- +Constructor for GMP on 32bit int +--SKIPIF-- + +--EXTENSIONS-- +gmp +--FILE-- + + string(10) "2147483647" +} +object(GMP)#1 (1) { + ["num"]=> + string(10) "2147483647" +} +object(GMP)#1 (1) { + ["num"]=> + string(10) "2147483647" +} +object(GMP)#1 (1) { + ["num"]=> + string(11) "-2147483648" +} +object(GMP)#1 (1) { + ["num"]=> + string(11) "-2147483648" +} diff --git a/ext/gmp/tests/construct_64bit.phpt b/ext/gmp/tests/construct_64bit.phpt new file mode 100644 index 000000000000..91a724641e9d --- /dev/null +++ b/ext/gmp/tests/construct_64bit.phpt @@ -0,0 +1,36 @@ +--TEST-- +Constructor for GMP on 64bit int +--SKIPIF-- + +--EXTENSIONS-- +gmp +--FILE-- + + string(19) "9223372036854775807" +} +object(GMP)#1 (1) { + ["num"]=> + string(19) "9223372036854775807" +} +object(GMP)#1 (1) { + ["num"]=> + string(19) "9223372036854775807" +} +object(GMP)#1 (1) { + ["num"]=> + string(20) "-9223372036854775808" +} +object(GMP)#1 (1) { + ["num"]=> + string(20) "-9223372036854775808" +} diff --git a/ext/gmp/tests/gmp_clrbit.phpt b/ext/gmp/tests/gmp_clrbit.phpt index 9dc63a87f5a5..f95964d1fc88 100644 --- a/ext/gmp/tests/gmp_clrbit.phpt +++ b/ext/gmp/tests/gmp_clrbit.phpt @@ -46,9 +46,9 @@ echo "Done\n"; ?> --EXPECTF-- string(1) "0" -ValueError: gmp_clrbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_clrbit(): Argument #2 ($index) must be between 0 and %d string(2) "-1" -ValueError: gmp_clrbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_clrbit(): Argument #2 ($index) must be between 0 and %d string(7) "1000000" string(7) "1000000" string(30) "238462734628347239571822592658" diff --git a/ext/gmp/tests/gmp_popcount.phpt b/ext/gmp/tests/gmp_popcount.phpt index 3b15a659c5ed..b2e8beb5e9cf 100644 --- a/ext/gmp/tests/gmp_popcount.phpt +++ b/ext/gmp/tests/gmp_popcount.phpt @@ -4,7 +4,6 @@ gmp_popcount() basic tests gmp --FILE-- --EXPECTF-- -ValueError: gmp_scan0(): Argument #2 ($start) must be between 0 and %d * %d +ValueError: gmp_scan0(): Argument #2 ($start) must be between 0 and %d int(2) int(0) int(5) diff --git a/ext/gmp/tests/gmp_scan1.phpt b/ext/gmp/tests/gmp_scan1.phpt index 83a70bcba263..f5b6bb7ecf60 100644 --- a/ext/gmp/tests/gmp_scan1.phpt +++ b/ext/gmp/tests/gmp_scan1.phpt @@ -28,7 +28,7 @@ try { echo "Done\n"; ?> --EXPECTF-- -ValueError: gmp_scan1(): Argument #2 ($start) must be between 0 and %d * %d +ValueError: gmp_scan1(): Argument #2 ($start) must be between 0 and %d int(1) int(12) int(9) diff --git a/ext/gmp/tests/gmp_setbit.phpt b/ext/gmp/tests/gmp_setbit.phpt index 09ce16ada7fe..8c50d8be6d4a 100644 --- a/ext/gmp/tests/gmp_setbit.phpt +++ b/ext/gmp/tests/gmp_setbit.phpt @@ -52,7 +52,7 @@ echo "Done\n"; ?> --EXPECTF-- string(2) "-1" -ValueError: gmp_setbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_setbit(): Argument #2 ($index) must be between 0 and %d string(1) "5" string(1) "1" string(1) "7" diff --git a/ext/gmp/tests/gmp_setbit_long.phpt b/ext/gmp/tests/gmp_setbit_long.phpt index e6d2dc262d59..909f7ee58bf8 100644 --- a/ext/gmp/tests/gmp_setbit_long.phpt +++ b/ext/gmp/tests/gmp_setbit_long.phpt @@ -3,7 +3,7 @@ gmp_setbit() with large index --EXTENSIONS-- gmp --SKIPIF-- - + 0 && $a < 0x8000000000; $a <<= 2) { $i = $a - 1; printf("%X\n", $i); @@ -41,5 +42,5 @@ FFFFFFFF 3FFFFFFFF FFFFFFFFF 3FFFFFFFFF -ValueError: gmp_setbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_setbit(): Argument #2 ($index) must be between 0 and %d Done diff --git a/ext/gmp/tests/gmp_testbit.phpt b/ext/gmp/tests/gmp_testbit.phpt index fb6497df5463..d291b3d2afb1 100644 --- a/ext/gmp/tests/gmp_testbit.phpt +++ b/ext/gmp/tests/gmp_testbit.phpt @@ -48,12 +48,12 @@ var_dump(gmp_strval($n)); echo "Done\n"; ?> --EXPECTF-- -ValueError: gmp_testbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_testbit(): Argument #2 ($index) must be between 0 and %d bool(false) bool(false) bool(false) bool(true) -ValueError: gmp_testbit(): Argument #2 ($index) must be between 0 and %d * %d +ValueError: gmp_testbit(): Argument #2 ($index) must be between 0 and %d bool(false) bool(true) string(7) "1000002" From b3fe0f71c15e5a07769aab9145a21aab2fcae2c5 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:40:12 +0200 Subject: [PATCH 10/12] Fix ext/shmop --- ext/shmop/shmop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c index 7903a294a037..598e965a8493 100644 --- a/ext/shmop/shmop.c +++ b/ext/shmop/shmop.c @@ -197,10 +197,10 @@ PHP_FUNCTION(shmop_open) goto err; } - if (shm.shm_segsz > ZEND_LONG_MAX) { - zend_argument_value_error(4, "is too large"); - goto err; - } +// if (shm.shm_segsz > ZEND_LONG_MAX) { +// zend_argument_value_error(4, "is too large"); +// goto err; +// } shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg); if (shmop->addr == (char*) -1) { From 84f5078ba5447e0b2667231d112578185b9fcb44 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 16 Nov 2025 11:46:08 +0100 Subject: [PATCH 11/12] Fix ext/opcache --- ext/opcache/zend_file_cache.c | 2 +- ext/opcache/zend_shared_alloc.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 0b6cabe42015..871fd66109bb 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -267,7 +267,7 @@ static void *zend_file_cache_serialize_interned(zend_string *str, } len = ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); - ret = (void*)(info->str_size | Z_UL(1)); + ret = (void*)(info->str_size | 1); zend_shared_alloc_register_xlat_entry(str, ret); zend_string *s = (zend_string*)ZCG(mem); diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 3d6d2a840c33..79542cd314fc 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -417,7 +417,7 @@ static zend_always_inline zend_ulong zend_rotr3(zend_ulong key) int zend_shared_memdup_size(void *source, size_t size) { void *old_p; - zend_ulong key = (zend_ulong)source; + zend_ulong key = (zend_ulong)(uintptr_t)source; key = zend_rotr3(key); if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) { @@ -434,7 +434,7 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, b zend_ulong key; if (get_xlat) { - key = (zend_ulong)source; + key = (zend_ulong)(uintptr_t)source; key = zend_rotr3(key); if ((old_p = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) != NULL) { /* we already duplicated this pointer */ @@ -446,7 +446,7 @@ static zend_always_inline void *_zend_shared_memdup(void *source, size_t size, b memcpy(retval, source, size); if (set_xlat) { if (!get_xlat) { - key = (zend_ulong)source; + key = (zend_ulong)(uintptr_t)source; key = zend_rotr3(key); } zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, retval); @@ -589,7 +589,7 @@ void zend_shared_alloc_restore_xlat_table(uint32_t checkpoint) void zend_shared_alloc_register_xlat_entry(const void *key_pointer, const void *value) { - zend_ulong key = (zend_ulong)key_pointer; + zend_ulong key = (zend_ulong)(uintptr_t)key_pointer; key = zend_rotr3(key); zend_hash_index_add_new_ptr(&ZCG(xlat_table), key, (void*)value); @@ -598,7 +598,7 @@ void zend_shared_alloc_register_xlat_entry(const void *key_pointer, const void * void *zend_shared_alloc_get_xlat_entry(const void *key_pointer) { void *retval; - zend_ulong key = (zend_ulong)key_pointer; + zend_ulong key = (zend_ulong)(uintptr_t)key_pointer; key = zend_rotr3(key); if ((retval = zend_hash_index_find_ptr(&ZCG(xlat_table), key)) == NULL) { From ed8bfa0a51b678fd272442be9febd3cb4613509e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Sun, 16 Nov 2025 12:40:32 +0100 Subject: [PATCH 12/12] Fix sapi/phpdbg --- sapi/phpdbg/phpdbg_bp.c | 8 ++++---- sapi/phpdbg/phpdbg_btree.c | 2 +- sapi/phpdbg/phpdbg_prompt.c | 2 +- sapi/phpdbg/phpdbg_watch.c | 30 +++++++++++++++--------------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 1233f0430121..6cb0b45e8b7f 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -513,7 +513,7 @@ PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_o opline_break.disabled = 0; opline_break.hits = 0; opline_break.id = brake->id; - opline_break.opline = brake->opline = (zend_ulong)(op_array->opcodes + brake->opline_num); + opline_break.opline = brake->opline = (zend_ulong)(uintptr_t)(op_array->opcodes + brake->opline_num); opline_break.name = NULL; opline_break.base = brake; if (op_array->scope) { @@ -809,7 +809,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline) /* { PHPDBG_G(flags) |= PHPDBG_HAS_OPLINE_BP; PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_OPLINE); - new_break.opline = (zend_ulong) opline; + new_break.opline = (zend_ulong)(uintptr_t)opline; new_break.base = NULL; zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong)(uintptr_t) opline, &new_break, sizeof(phpdbg_breakline_t)); @@ -817,7 +817,7 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline) /* { phpdbg_notice("Breakpoint #%d added at #"ZEND_ULONG_FMT, new_break.id, new_break.opline); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); } else { - phpdbg_error("Breakpoint exists for opline #"ZEND_ULONG_FMT, (zend_ulong) opline); + phpdbg_error("Breakpoint exists for opline #"ZEND_ULONG_FMT, (zend_ulong)(uintptr_t)opline); } } /* }}} */ @@ -1068,7 +1068,7 @@ static inline bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend_exec } break; case ADDR_PARAM: { - return ((zend_ulong)(phpdbg_opline_ptr_t)execute_data->opline == param->addr); + return ((zend_ulong)(uintptr_t)(phpdbg_opline_ptr_t)execute_data->opline == param->addr); } break; default: { diff --git a/sapi/phpdbg/phpdbg_btree.c b/sapi/phpdbg/phpdbg_btree.c index 788e9b464c14..5e58f63ce09c 100644 --- a/sapi/phpdbg/phpdbg_btree.c +++ b/sapi/phpdbg/phpdbg_btree.c @@ -253,7 +253,7 @@ void phpdbg_btree_branch_dump(phpdbg_btree_branch *branch, zend_ulong depth) { phpdbg_btree_branch_dump(branch->branches[0], depth); phpdbg_btree_branch_dump(branch->branches[1], depth); } else { - fprintf(stderr, "%p: %p\n", (void *) branch->result.idx, branch->result.ptr); + fprintf(stderr, ZEND_ULONG_FMT": %p\n", branch->result.idx, branch->result.ptr); } } } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index d6249ae068da..5428102a26eb 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1712,7 +1712,7 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ /* perform seek operation */ if ((PHPDBG_G(flags) & PHPDBG_SEEK_MASK) && !(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { /* current address */ - zend_ulong address = (zend_ulong) execute_data->opline; + zend_ulong address = (zend_ulong)(uintptr_t)execute_data->opline; if (PHPDBG_G(seek_ex) != execute_data) { if (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) { diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index a2e39e15a6ca..632a837c4310 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -226,7 +226,7 @@ void phpdbg_print_watch_diff(phpdbg_watchtype type, zend_string *name, void *old /* ### LOW LEVEL WATCHPOINT HANDLING ### */ static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(phpdbg_btree *tree, void *addr) { phpdbg_watchpoint_t *watch; - phpdbg_btree_result *result = phpdbg_btree_find_closest(tree, (zend_ulong) phpdbg_get_page_boundary(addr) + phpdbg_pagesize - 1); + phpdbg_btree_result *result = phpdbg_btree_find_closest(tree, (zend_ulong)(uintptr_t)phpdbg_get_page_boundary(addr) + phpdbg_pagesize - 1); if (result == NULL) { return NULL; @@ -343,14 +343,14 @@ void *phpdbg_watchpoint_userfaultfd_thread(void *phpdbg_globals_ptr) { /* ### REGISTER WATCHPOINT ### To be used only by watch element and collision managers ### */ static inline void phpdbg_store_watchpoint_btree(phpdbg_watchpoint_t *watch) { #if ZEND_DEBUG - phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr); + phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)(uintptr_t)watch->addr.ptr); ZEND_ASSERT(res == NULL || res->ptr == watch); #endif - phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr, watch); + phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong)(uintptr_t)watch->addr.ptr, watch); } static inline void phpdbg_remove_watchpoint_btree(phpdbg_watchpoint_t *watch) { - phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr); + phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong)(uintptr_t)watch->addr.ptr); } /* ### SET WATCHPOINT ADDR ### To be used only by watch element and collision managers ### */ @@ -544,7 +544,7 @@ phpdbg_watch_element *phpdbg_add_watch_element(phpdbg_watchpoint_t *watch, phpdb if (is_new) { *is_new = true; } - if ((res = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr)) == NULL) { + if ((res = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)(uintptr_t) watch->addr.ptr)) == NULL) { phpdbg_watchpoint_t *mem = emalloc(sizeof(*mem)); *mem = *watch; watch = mem; @@ -728,12 +728,12 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) { phpdbg_btree_result *res; phpdbg_watch_ht_info *hti; ZEND_ASSERT(element->parent_container); - if (!(res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) element->parent_container))) { + if (!(res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong)(uintptr_t)element->parent_container))) { hti = emalloc(sizeof(*hti)); hti->ht = element->parent_container; zend_hash_init(&hti->watches, 0, NULL, ZVAL_PTR_DTOR, 0); - phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong) hti->ht, hti); + phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong)(uintptr_t)hti->ht, hti); phpdbg_set_addr_watchpoint(HT_GET_DATA_ADDR(hti->ht), HT_HASH_SIZE(hti->ht->nTableMask), &hti->hash_watch); hti->hash_watch.type = WATCH_ON_HASHDATA; @@ -751,7 +751,7 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) { void phpdbg_unwatch_parent_ht(phpdbg_watch_element *element) { if (element->flags & PHPDBG_WATCH_HT_REGISTERED) { - phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) element->parent_container); + phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong)(uintptr_t) element->parent_container); ZEND_ASSERT(element->parent_container); element->flags &= ~PHPDBG_WATCH_HT_REGISTERED; if (res) { @@ -759,7 +759,7 @@ void phpdbg_unwatch_parent_ht(phpdbg_watch_element *element) { if (zend_hash_num_elements(&hti->watches) == 1) { zend_hash_destroy(&hti->watches); - phpdbg_btree_delete(&PHPDBG_G(watch_HashTables), (zend_ulong) hti->ht); + phpdbg_btree_delete(&PHPDBG_G(watch_HashTables), (zend_ulong)(uintptr_t)hti->ht); phpdbg_remove_watchpoint_btree(&hti->hash_watch); phpdbg_deactivate_watchpoint(&hti->hash_watch); efree(hti); @@ -1141,7 +1141,7 @@ void phpdbg_check_watchpoint(phpdbg_watchpoint_t *watch) { zval *zv; ZEND_HASH_MAP_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_RECURSIVE) { - phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) HT_WATCH_HT(watch)); + phpdbg_btree_result *res = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong)(uintptr_t)HT_WATCH_HT(watch)); phpdbg_watch_ht_info *hti = res ? res->ptr : NULL; ZEND_HASH_REVERSE_FOREACH_KEY_VAL(HT_WATCH_HT(watch), idx, str, zv) { @@ -1254,7 +1254,7 @@ void phpdbg_reenable_memory_watches(void) { res = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), page + phpdbg_pagesize - 1); if (res) { watch = res->ptr; - if ((char *) page < (char *) watch->addr.ptr + watch->size) { + if ((char *)(intptr_t)page < (char *) watch->addr.ptr + watch->size) { #ifdef HAVE_USERFAULTFD_WRITEFAULT if (PHPDBG_G(watch_userfaultfd)) { struct uffdio_writeprotect protect = { @@ -1268,7 +1268,7 @@ void phpdbg_reenable_memory_watches(void) { } else #endif { - mprotect((void *) page, phpdbg_pagesize, PROT_READ); + mprotect((void *)(intptr_t)page, phpdbg_pagesize, PROT_READ); } } } @@ -1301,7 +1301,7 @@ int phpdbg_print_changed_zvals(void) { } if ((res = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), page - 1))) { watch = res->ptr; - if ((char *) page < (char *) watch->addr.ptr + watch->size) { + if ((char *)(intptr_t)page < (char *) watch->addr.ptr + watch->size) { phpdbg_check_watchpoint(watch); } } @@ -1328,7 +1328,7 @@ void phpdbg_watch_efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { /* only do expensive checks if there are any watches at all */ if (zend_hash_num_elements(&PHPDBG_G(watch_elements))) { - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) ptr))) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)(uintptr_t)ptr))) { phpdbg_watchpoint_t *watch = result->ptr; if (watch->type != WATCH_ON_HASHDATA) { phpdbg_remove_watchpoint(watch); @@ -1348,7 +1348,7 @@ void phpdbg_watch_efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { } /* special case watchpoints as they aren't on ptr but on ptr + HT_WATCH_OFFSET */ - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), HT_WATCH_OFFSET + (zend_ulong) ptr))) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), HT_WATCH_OFFSET + (zend_ulong)(uintptr_t)ptr))) { phpdbg_watchpoint_t *watch = result->ptr; if (watch->type == WATCH_ON_HASHTABLE) { phpdbg_remove_watchpoint(watch);