From 9a2d8ecc0ee8d741e3921ccc4d63d9c96c9f3f7f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:36:17 +0200 Subject: [PATCH 01/18] Use int64 for zend_long --- Zend/Zend.m4 | 38 ++++++++++++++++++++++++++++++++++++++ Zend/zend_alloc.c | 12 ++++++------ 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 | 4 ++-- Zend/zend_operators.h | 8 ++++---- Zend/zend_range_check.h | 23 +++++++++++++++++++---- Zend/zend_string.c | 5 ++--- Zend/zend_string.h | 2 +- Zend/zend_types.h | 26 +++++++++++++------------- Zend/zend_vm_execute.h | 6 +++--- Zend/zend_vm_execute.skl | 6 +++--- Zend/zend_vm_trace_map.h | 2 +- Zend/zend_weakrefs.c | 10 +++++----- main/main_arginfo.h | 1 + 18 files changed, 111 insertions(+), 58 deletions(-) diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 45791a34c5f80..aa98bd9e587a1 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -216,6 +216,7 @@ AX_CHECK_COMPILE_FLAG([-fno-common], [-Werror]) ZEND_CHECK_ALIGNMENT +ZEND_CHECK_INT64 ZEND_CHECK_SIGNALS ZEND_CHECK_MAX_EXECUTION_TIMERS ]) @@ -419,6 +420,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 f2f801db63396..a204463024a0c 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -174,7 +174,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)) @@ -587,7 +587,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); @@ -610,7 +610,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);} } @@ -2065,7 +2065,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 @@ -3262,7 +3262,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) { @@ -3483,7 +3483,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 f3f6d1b75aec1..5add159498290 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -12134,7 +12134,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 734494d252da0..f27cb449b8400 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2132,11 +2132,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)); @@ -3094,7 +3094,7 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z } 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); @@ -3227,7 +3227,7 @@ static zend_never_inline bool ZEND_FASTCALL zend_isset_dim_slow(zval *container, 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; @@ -3266,7 +3266,7 @@ static zend_never_inline bool ZEND_FASTCALL zend_isempty_dim_slow(zval *containe 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 6d2a6195cd52c..372b98a567519 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1215,7 +1215,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_long)(uintptr_t)ce); + zend_hash_index_add_empty_element(CG(unlinked_uses), (zend_ulong)(uintptr_t)ce); return ce; } return NULL; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a6ea91a7425b9..d2758ea2ca92e 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -179,7 +179,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) child); + zend_hash_index_del(ht, (zend_ulong)(uintptr_t)child); if (node->children == 2) { zend_generator *other_child; ZEND_HASH_FOREACH_PTR(ht, other_child) { @@ -533,11 +533,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_ulong)(uintptr_t)node->child.single, node->child.single); node->child.ht = ht; } - zend_hash_index_add_new_ptr(node->child.ht, (zend_ulong) child, child); + zend_hash_index_add_new_ptr(node->child.ht, (zend_ulong)(uintptr_t)child, child); } ++node->children; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index d27cca5b76187..d40ebfe4ea605 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -3299,7 +3299,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_long)(uintptr_t)ce) == SUCCESS) { + && zend_hash_index_del(CG(unlinked_uses), (zend_ulong)(uintptr_t)ce) == SUCCESS) { zend_exception_uncaught_error( "During inheritance of %s with variance dependencies", ZSTR_VAL(ce->name)); } @@ -3584,7 +3584,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_long)(uintptr_t) ce); + zend_hash_index_del(CG(unlinked_uses), (zend_ulong)(uintptr_t) ce); } orig_linking_class = CG(current_linking_class); diff --git a/Zend/zend_long.h b/Zend/zend_long.h index 3796f1c5ababb..56ed74a9c823d 100644 --- a/Zend/zend_long.h +++ b/Zend/zend_long.h @@ -23,7 +23,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 @@ -97,7 +97,7 @@ typedef int32_t zend_off_t; do { \ int st = snprintf((s), (len), ZEND_LONG_FMT, (i)); \ (s)[st] = '\0'; \ - } while (0) + } while (0) # define ZEND_ATOL(s) atol((s)) # endif # define ZEND_STRTOL_PTR strtol diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index a7537d1b3ef33..8778af0baf840 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -519,11 +519,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 9c822493fa3ef..32fb9cb6069c8 100644 --- a/Zend/zend_range_check.h +++ b/Zend/zend_range_check.h @@ -59,9 +59,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 c864a847af39f..175d3407280e9 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -393,7 +393,7 @@ ZEND_API bool ZEND_FASTCALL I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_va } #endif -#if defined(__GNUC__) && defined(__i386__) +#if SIZEOF_SIZE_T == SIZEOF_ZEND_LONG && defined(__GNUC__) && defined(__i386__) 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); @@ -430,8 +430,7 @@ 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__) +#elif SIZEOF_SIZE_T == SIZEOF_ZEND_LONG && 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); diff --git a/Zend/zend_string.h b/Zend/zend_string.h index ac9a7465c8767..628a5b6721955 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -361,7 +361,7 @@ static zend_always_inline bool zend_string_equals_cstr(const zend_string *s1, co return ZSTR_LEN(s1) == s2_length && !memcmp(ZSTR_VAL(s1), s2, s2_length); } -#if defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) && !defined(__ILP32__))) +#if SIZEOF_SIZE_T == SIZEOF_ZEND_LONG && defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) && !defined(__ILP32__))) BEGIN_EXTERN_C() ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2); END_EXTERN_C() diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 4a6d00b9d73ea..840f934a234cb 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -62,19 +62,19 @@ typedef enum { typedef ZEND_RESULT_CODE zend_result; -#ifdef ZEND_ENABLE_ZVAL_LONG64 -# ifdef ZEND_WIN32 -# define ZEND_SIZE_MAX _UI64_MAX -# else -# define ZEND_SIZE_MAX SIZE_MAX -# endif -#else -# if defined(ZEND_WIN32) -# define ZEND_SIZE_MAX _UI32_MAX -# else -# define ZEND_SIZE_MAX SIZE_MAX -# endif -#endif +// #ifdef ZEND_ENABLE_ZVAL_LONG64 +// # ifdef ZEND_WIN32 +// # define ZEND_SIZE_MAX _UI64_MAX +// # else +// # define ZEND_SIZE_MAX SIZE_MAX +// # endif +// #else +// # if defined(ZEND_WIN32) +// # define ZEND_SIZE_MAX _UI32_MAX +// # else +// # define ZEND_SIZE_MAX SIZE_MAX +// # endif +// #endif #ifdef ZTS #define ZEND_TLS static TSRM_TLS diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e79d843e6abf9..783de9ca6db44 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -68178,7 +68178,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_long)(uintptr_t)zend_opcode_handlers[i], &tmp); + zend_hash_index_add(zend_handlers_table, (zend_ulong)(uintptr_t)zend_opcode_handlers[i], &tmp); } } @@ -68189,7 +68189,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_long)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); op->handler = (const void *)(uintptr_t)Z_LVAL_P(zv); } @@ -68209,7 +68209,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_long)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #else diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 6fecd39346a70..90e2fc9061d90 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -113,7 +113,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_long)(uintptr_t)zend_opcode_handlers[i], &tmp); + zend_hash_index_add(zend_handlers_table, (zend_ulong)(uintptr_t)zend_opcode_handlers[i], &tmp); } } @@ -124,7 +124,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_long)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); op->handler = (const void *)(uintptr_t)Z_LVAL_P(zv); } @@ -144,7 +144,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_long)(uintptr_t)op->handler); + zv = zend_hash_index_find(zend_handlers_table, (zend_ulong)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; #else diff --git a/Zend/zend_vm_trace_map.h b/Zend/zend_vm_trace_map.h index d84aa0442d263..f41335989c4a8 100644 --- a/Zend/zend_vm_trace_map.h +++ b/Zend/zend_vm_trace_map.h @@ -20,7 +20,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_long)(intptr_t)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 cf363cd12595c..c48a478c61d79 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) payload, payload); + zend_hash_index_add_new_ptr(ht, (zend_ulong)(uintptr_t)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) tagged_ptr, tagged_ptr); - zend_hash_index_add_new_ptr(ht, (zend_ulong) payload, payload); + 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); /* 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) payload); + void *old_payload = zend_hash_index_find_ptr(ht, (zend_ulong)(uintptr_t)payload); ZEND_ASSERT(old_payload && "Weakref not registered?"); ZEND_ASSERT(old_payload == payload); #endif - zend_hash_index_del(ht, (zend_ulong) payload); + zend_hash_index_del(ht, (zend_ulong)(uintptr_t)payload); if (zend_hash_num_elements(ht) == 0) { GC_DEL_FLAGS(object, IS_OBJ_WEAKLY_REFERENCED); zend_hash_destroy(ht); diff --git a/main/main_arginfo.h b/main/main_arginfo.h index 922af3aff0629..26ab37ad5cf61 100644 --- a/main/main_arginfo.h +++ b/main/main_arginfo.h @@ -36,6 +36,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 5519c0078ceb073b1479cfa82f55ae095ed3b1f9 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 9 Jul 2025 22:56:18 +0200 Subject: [PATCH 02/18] Added PHP_SYS_SIZE --- main/main.stub.php | 5 +++++ main/main_arginfo.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/main/main.stub.php b/main/main.stub.php index 3359d4a1cd0bf..a8b3b70c1d2d0 100644 --- a/main/main.stub.php +++ b/main/main.stub.php @@ -163,6 +163,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 26ab37ad5cf61..17fe9f0cbf2e2 100644 --- a/main/main_arginfo.h +++ b/main/main_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: cb5c9a3e48b18a773264378099267550ca9e4fc1 */ + * Stub hash: a238f2ed316879726cc1c622f801efbd77e804e2 */ static void register_main_symbols(int module_number) { From 93e6975d51bca5303b47eff1d8fa2b8dfc9eae7e Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:37:21 +0200 Subject: [PATCH 03/18] Fix ext/standard --- ext/standard/file.c | 2 + ext/standard/formatted_print.c | 2 +- ext/standard/head.c | 5 +- ext/standard/head.h | 2 +- ext/standard/math.c | 6 +- ext/standard/string.c | 62 +++++++++++++++---- ext/standard/tests/strings/gh15613.phpt | 2 +- .../sprintf_rope_optimization_004.phpt | 16 ++--- .../tests/strings/str_pad_variation1.phpt | 11 ++-- .../tests/strings/str_pad_variation5.phpt | 24 +++---- 10 files changed, 88 insertions(+), 44 deletions(-) diff --git a/ext/standard/file.c b/ext/standard/file.c index ab6ed4fbadd2d..44ae4006decc1 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -498,10 +498,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; diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index b2c287c02900c..9a72b8267f46d 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -103,7 +103,7 @@ php_sprintf_appendstring(zend_string **buffer, size_t *pos, char *add, if (req_size > ZSTR_LEN(*buffer)) { size_t size = ZSTR_LEN(*buffer); while (req_size > size) { - if (size > ZEND_SIZE_MAX/2) { + if (size > SIZE_MAX/2) { zend_error_noreturn(E_ERROR, "Field width %zd is too long", req_size); } size <<= 1; diff --git a/ext/standard/head.c b/ext/standard/head.c index ccef4be16bdfd..96f1e7be7e319 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -77,7 +77,7 @@ PHPAPI bool php_header(void) } #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 url_encode) { @@ -110,7 +110,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 32c2570a53255..7a7af61dc9606 100644 --- a/ext/standard/head.h +++ b/ext/standard/head.h @@ -28,7 +28,7 @@ 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 url_encode); diff --git a/ext/standard/math.c b/ext/standard/math.c index 142d473864f75..18e065c33ae77 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -1225,8 +1225,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 @@ -1256,7 +1256,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 (dec < -(zend_long)(sizeof(powers) / sizeof(powers[0]) - 1)) { tmpnum = 0; } else { power = powers[-dec]; diff --git a/ext/standard/string.c b/ext/standard/string.c index 75be1f1dcab1c..8beb06fef42d9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2225,13 +2225,19 @@ 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)) { - RETURN_EMPTY_STRING(); + } else { +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (UNEXPECTED(f > SIZE_MAX)) { + f = SIZE_MAX; + } +#endif + if ((size_t)f > ZSTR_LEN(str)) { + RETURN_EMPTY_STRING(); + } } if (!len_is_null) { @@ -2239,13 +2245,19 @@ 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 SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (UNEXPECTED(l > SIZE_MAX)) { + l = SIZE_MAX; + } +#endif + 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; @@ -2360,8 +2372,15 @@ PHP_FUNCTION(substr_replace) if (f < 0) { f = 0; } - } else if ((size_t)f > ZSTR_LEN(str)) { - f = ZSTR_LEN(str); + } else { +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (UNEXPECTED(f > SIZE_MAX)) { + f = SIZE_MAX; + } +#endif + if ((size_t)f > ZSTR_LEN(str)) { + f = ZSTR_LEN(str); + } } /* if "length" position is negative, set it to the length * needed to stop that many chars from the end of the string @@ -2373,6 +2392,12 @@ PHP_FUNCTION(substr_replace) } } +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (UNEXPECTED(l > SIZE_MAX)) { + l = SIZE_MAX; + } +#endif + if ((size_t)l > ZSTR_LEN(str)) { l = ZSTR_LEN(str); } @@ -2522,6 +2547,12 @@ PHP_FUNCTION(substr_replace) } } +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (UNEXPECTED(l > SIZE_MAX)) { + l = SIZE_MAX; + } +#endif + 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)) { @@ -5756,6 +5787,13 @@ PHP_FUNCTION(str_pad) Z_PARAM_LONG(pad_type_val) ZEND_PARSE_PARAMETERS_END(); +#if SIZEOF_SIZE_T < SIZEOF_ZEND_LONG + if (pad_length > SIZE_MAX/2) { + zend_argument_value_error(2, "must be lower or equal to %zd", SIZE_MAX/2); + RETURN_THROWS(); + } +#endif + /* 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)) { diff --git a/ext/standard/tests/strings/gh15613.phpt b/ext/standard/tests/strings/gh15613.phpt index 8f40ee820c9a2..5afeac1dd16a4 100644 --- a/ext/standard/tests/strings/gh15613.phpt +++ b/ext/standard/tests/strings/gh15613.phpt @@ -2,7 +2,7 @@ GH-15613 overflow on hex strings repeater value --SKIPIF-- --INI-- memory_limit=-1 diff --git a/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt b/ext/standard/tests/strings/sprintf_rope_optimization_004.phpt index 27837e518a718..1e46a6570f77a 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 cb71e61156fcd..11471e58a46a6 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_variation5.phpt b/ext/standard/tests/strings/str_pad_variation5.phpt index 1a65366c823ce..9434ea8883e7c 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-1)-1) ); -?> --EXPECTF-- -*** Testing str_pad() function: with large value for for 'pad_length' argument *** +ValueError: str_pad(): Argument #2 ($length) must be lower or equal to %d Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d From be34032441ee160bde995c8afc0d7bdf6dfe663f Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 9 Jul 2025 23:42:06 +0200 Subject: [PATCH 04/18] 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 fee90e42b574f..c7179fa1b63c4 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -271,7 +271,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 37dbe59f3d55c..a6bb96db582e8 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -403,7 +403,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) { @@ -420,7 +420,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 */ @@ -432,7 +432,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); @@ -575,7 +575,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); @@ -584,7 +584,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 d84a8412883378197fe4048d3027c5e90c4a4bef Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:36:51 +0200 Subject: [PATCH 05/18] 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 ae7f62fb8f734..35c1f6554ffcd 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -672,6 +672,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) { @@ -874,7 +886,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; @@ -1125,7 +1137,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); @@ -1208,8 +1220,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"); @@ -3915,7 +3926,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 f5f43bc7dfb0f..81764d9bf105a 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -139,7 +139,7 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime); #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 fa2f6fc252b71c80d2240b22429b512926ce7f63 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:38:26 +0200 Subject: [PATCH 06/18] Fix ext/socket --- ext/sockets/sendrecvmsg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index cd7fd4839fb0f..021a6d23c9c2f 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -316,7 +316,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(); From 51a60a33dc266f9c683eb4522bd7204d664b61a1 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:39:43 +0200 Subject: [PATCH 07/18] 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 | 4 +- ext/gmp/tests/gmp_testbit.phpt | 4 +- 10 files changed, 204 insertions(+), 26 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 8cf20c90fc7a2..c3dd6c646d5c6 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -106,6 +106,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 +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); + } +} + +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; +} + +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); @@ -129,7 +192,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; } @@ -145,7 +208,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; } @@ -243,7 +306,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; @@ -251,8 +314,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)); } @@ -712,7 +775,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; } @@ -862,7 +925,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)); } /* }}} */ @@ -1526,8 +1589,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 */ @@ -1543,7 +1611,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(); } @@ -1569,7 +1637,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(); } @@ -1590,7 +1658,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(); } @@ -1602,12 +1670,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); } /* }}} */ @@ -1615,13 +1692,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); } /* }}} */ @@ -1630,6 +1716,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) @@ -1637,11 +1724,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); } /* }}} */ @@ -1650,6 +1745,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) @@ -1657,11 +1754,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 0000000000000..581d1d5b3eba7 --- /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 0000000000000..91a724641e9d4 --- /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 afefa740f10eb..c2175f1c3597e 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" -gmp_clrbit(): Argument #2 ($index) must be between 0 and %d * %d +gmp_clrbit(): Argument #2 ($index) must be between 0 and %d string(2) "-1" -gmp_clrbit(): Argument #2 ($index) must be between 0 and %d * %d +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 3b61eec5b7aac..d637b8c40cd35 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-- -gmp_scan0(): Argument #2 ($start) must be between 0 and %d * %d +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 8021f7e679d86..5b084887d2f18 100644 --- a/ext/gmp/tests/gmp_scan1.phpt +++ b/ext/gmp/tests/gmp_scan1.phpt @@ -28,7 +28,7 @@ try { echo "Done\n"; ?> --EXPECTF-- -gmp_scan1(): Argument #2 ($start) must be between 0 and %d * %d +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 775042ef9737f..d16323cdc711a 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" -gmp_setbit(): Argument #2 ($index) must be between 0 and %d * %d +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 bbd472de967e6..1adcc5938bda8 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; + var_dump($i); printf("%X\n", $i); try { gmp_setbit($n, $i, 1); diff --git a/ext/gmp/tests/gmp_testbit.phpt b/ext/gmp/tests/gmp_testbit.phpt index 1cef8cd4166b2..08e4c516f83bc 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-- -gmp_testbit(): Argument #2 ($index) must be between 0 and %d * %d +gmp_testbit(): Argument #2 ($index) must be between 0 and %d bool(false) bool(false) bool(false) bool(true) -gmp_testbit(): Argument #2 ($index) must be between 0 and %d * %d +gmp_testbit(): Argument #2 ($index) must be between 0 and %d bool(false) bool(true) string(7) "1000002" From 9a5fe687115a8301b69abe64d6bd3dcf456c002a Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Mon, 7 Jul 2025 09:40:12 +0200 Subject: [PATCH 08/18] 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 67f060f3c82cd..ebf07908fbf80 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 7d0f1bd0c1b1aaa0f45dc561c00721d110c72801 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Wed, 9 Jul 2025 22:44:22 +0200 Subject: [PATCH 09/18] GH workflow --- .github/workflows/push.yml | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2f82179b90ec6..189d584f733ae 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -192,6 +192,66 @@ jobs: runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 + LINUX_X32_INT64: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' + name: LINUX_X32_INT64_DEBUG_ZTS + runs-on: ubuntu-latest + timeout-minutes: 50 + container: + image: ubuntu:24.04 + env: + MYSQL_TEST_HOST: mysql + PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test + PDO_MYSQL_TEST_HOST: mysql + PDO_FIREBIRD_TEST_DSN: firebird:dbname=firebird:test.fdb + services: + mysql: + image: mysql:8.3 + ports: + - 3306:3306 + env: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + firebird: + image: jacobalberty/firebird + ports: + - 3050:3050 + env: + ISC_PASSWORD: test + FIREBIRD_DATABASE: test.fdb + FIREBIRD_USER: test + FIREBIRD_PASSWORD: test + steps: + - name: git checkout + uses: actions/checkout@v4 + - name: apt + uses: ./.github/actions/apt-x32 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" + append-timestamp: false + - name: ./configure + uses: ./.github/actions/configure-x32 + with: + configurationParameters: >- + --enable-debug + --enable-zts + --enable-zend-int64 + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-linux-x32 + - name: Test + if: matrix.asan == false + uses: ./.github/actions/test-linux + - name: Test Tracing JIT + uses: ./.github/actions/test-linux + with: + jitType: tracing + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.enable_cli=1 MACOS_DEBUG_NTS: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' strategy: From cf5f76ae6003cb1c19df7465040b76b39c8129d3 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 08:59:18 +0200 Subject: [PATCH 10/18] Fix ext/pcntl --- ext/pcntl/pcntl.c | 14 +++++++------- ext/pcntl/pcntl.stub.php | 6 +++--- ext/pcntl/pcntl_arginfo.h | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index e11de304b1b79..d3d7c6e637667 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -238,8 +238,8 @@ PHP_RSHUTDOWN_FUNCTION(pcntl) /* Reset all signals to their default disposition */ ZEND_HASH_FOREACH_NUM_KEY_VAL(&PCNTL_G(php_signal_table), signo, handle) { - if (Z_TYPE_P(handle) != IS_LONG || Z_LVAL_P(handle) != (zend_long)SIG_DFL) { - php_signal(signo, (Sigfunc *)(zend_long)SIG_DFL, 0); + if (Z_TYPE_P(handle) != IS_LONG || Z_LVAL_P(handle) != (zend_long)(intptr_t)SIG_DFL) { + php_signal(signo, (Sigfunc *)(intptr_t)SIG_DFL, 0); } } ZEND_HASH_FOREACH_END(); @@ -825,11 +825,11 @@ PHP_FUNCTION(pcntl_signal) /* Special long value case for SIG_DFL and SIG_IGN */ if (Z_TYPE_P(handle) == IS_LONG) { - if (Z_LVAL_P(handle) != (zend_long) SIG_DFL && Z_LVAL_P(handle) != (zend_long) SIG_IGN) { + if (Z_LVAL_P(handle) != (zend_long)(intptr_t)SIG_DFL && Z_LVAL_P(handle) != (zend_long)(intptr_t)SIG_IGN) { zend_argument_value_error(2, "must be either SIG_DFL or SIG_IGN when an integer value is given"); RETURN_THROWS(); } - if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == (void *)SIG_ERR) { + if (php_signal(signo, (Sigfunc *)(intptr_t)Z_LVAL_P(handle), (int) restart_syscalls) == (void *)SIG_ERR) { PCNTL_G(last_error) = errno; php_error_docref(NULL, E_WARNING, "Error assigning signal"); RETURN_FALSE; @@ -885,7 +885,7 @@ PHP_FUNCTION(pcntl_signal_get_handler) if ((prev_handle = zend_hash_index_find(&PCNTL_G(php_signal_table), signo)) != NULL) { RETURN_COPY(prev_handle); } else { - RETURN_LONG((zend_long)SIG_DFL); + RETURN_LONG((zend_long)(intptr_t)SIG_DFL); } } @@ -1151,11 +1151,11 @@ static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_sigi case SIGFPE: case SIGSEGV: case SIGBUS: - add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr); + add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)(intptr_t)siginfo->si_addr); break; #if defined(SIGPOLL) && !defined(__CYGWIN__) case SIGPOLL: - add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, siginfo->si_band); + add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, (zend_long)(intptr_t)siginfo->si_band); # ifdef si_fd add_assoc_long_ex(user_siginfo, "fd", sizeof("fd")-1, siginfo->si_fd); # endif diff --git a/ext/pcntl/pcntl.stub.php b/ext/pcntl/pcntl.stub.php index 3f3800c50abe5..3c6b2f1d270ef 100644 --- a/ext/pcntl/pcntl.stub.php +++ b/ext/pcntl/pcntl.stub.php @@ -108,17 +108,17 @@ /** * @var int - * @cvalue LONG_CONST(SIG_IGN) + * @cvalue LONG_CONST((intptr_t)SIG_IGN) */ const SIG_IGN = UNKNOWN; /** * @var int - * @cvalue LONG_CONST(SIG_DFL) + * @cvalue LONG_CONST((intptr_t)SIG_DFL) */ const SIG_DFL = UNKNOWN; /** * @var int - * @cvalue LONG_CONST(SIG_ERR) + * @cvalue LONG_CONST((intptr_t)SIG_ERR) */ const SIG_ERR = UNKNOWN; /** diff --git a/ext/pcntl/pcntl_arginfo.h b/ext/pcntl/pcntl_arginfo.h index 8b2367a7c7042..afd597266a9f6 100644 --- a/ext/pcntl/pcntl_arginfo.h +++ b/ext/pcntl/pcntl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5e4b066d70fa264c7de3ba4b2113369c34c33e43 */ + * Stub hash: d36a985d8960a6afc84285b12b4e72ed3807ce35 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -332,9 +332,9 @@ static void register_pcntl_symbols(int module_number) #if defined(HAVE_WAITID) && defined(HAVE_FREEBSD_IDTYPES) REGISTER_LONG_CONSTANT("P_JAILID", LONG_CONST(P_JAILID), CONST_PERSISTENT); #endif - REGISTER_LONG_CONSTANT("SIG_IGN", LONG_CONST(SIG_IGN), CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SIG_DFL", LONG_CONST(SIG_DFL), CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SIG_ERR", LONG_CONST(SIG_ERR), CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SIG_IGN", LONG_CONST((intptr_t)SIG_IGN), CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SIG_DFL", LONG_CONST((intptr_t)SIG_DFL), CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SIG_ERR", LONG_CONST((intptr_t)SIG_ERR), CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SIGHUP", LONG_CONST(SIGHUP), CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SIGINT", LONG_CONST(SIGINT), CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SIGQUIT", LONG_CONST(SIGQUIT), CONST_PERSISTENT); From 81eae2ef4e90283991149e24b76457f7fbc84e7d Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 09:24:47 +0200 Subject: [PATCH 11/18] Fix ext/soap --- ext/soap/php_encoding.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 8423f50fd4b8e..fa39d5374987e 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -278,7 +278,7 @@ static bool soap_check_zval_ref(zval *data, xmlNodePtr node) { if (Z_TYPE_P(data) == IS_OBJECT) { data = (zval*)Z_OBJ_P(data); } - if ((node_ptr = zend_hash_index_find_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)data)) != NULL) { + if ((node_ptr = zend_hash_index_find_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)(uintptr_t)data)) != NULL) { xmlAttrPtr attr = node_ptr->properties; char *id; smart_str prefix = {0}; @@ -324,7 +324,7 @@ static bool soap_check_zval_ref(zval *data, xmlNodePtr node) { smart_str_free(&prefix); return 1; } else { - zend_hash_index_update_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)data, node); + zend_hash_index_update_ptr(SOAP_GLOBAL(ref_map), (zend_ulong)(uintptr_t)data, node); } } return 0; @@ -335,7 +335,7 @@ static bool soap_check_xml_ref(zval *data, xmlNodePtr node) zval *data_ptr; if (SOAP_GLOBAL(ref_map)) { - if ((data_ptr = zend_hash_index_find(SOAP_GLOBAL(ref_map), (zend_ulong)node)) != NULL) { + if ((data_ptr = zend_hash_index_find(SOAP_GLOBAL(ref_map), (zend_ulong)(uintptr_t)node)) != NULL) { if (!Z_REFCOUNTED_P(data) || !Z_REFCOUNTED_P(data_ptr) || Z_COUNTED_P(data) != Z_COUNTED_P(data_ptr)) { @@ -351,7 +351,7 @@ static bool soap_check_xml_ref(zval *data, xmlNodePtr node) static void soap_add_xml_ref(zval *data, xmlNodePtr node) { if (SOAP_GLOBAL(ref_map)) { - zend_hash_index_update(SOAP_GLOBAL(ref_map), (zend_ulong)node, data); + zend_hash_index_update(SOAP_GLOBAL(ref_map), (zend_ulong)(uintptr_t)node, data); } } From d0334511d3b815b7758e93eb7323d794b4f9e4ae Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 09:46:15 +0200 Subject: [PATCH 12/18] Fix ext/zend_test --- ext/zend_test/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 14aad0d1a322e..51daf01b9a906 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -857,7 +857,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 1ea92b283746d33b0e6b0a5e834ee9604da1f63b Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 11:11:30 +0200 Subject: [PATCH 13/18] Fix sapi/phpdbg --- sapi/phpdbg/phpdbg_bp.c | 14 ++++----- sapi/phpdbg/phpdbg_btree.c | 2 +- sapi/phpdbg/phpdbg_prompt.c | 10 +++---- sapi/phpdbg/phpdbg_watch.c | 58 ++++++++++++++++++------------------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 0a94adf21305a..655d524784d36 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -515,7 +515,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) { @@ -805,21 +805,21 @@ PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len) PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline) /* {{{ */ { - if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) { + if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong)(uintptr_t) opline)) { phpdbg_breakline_t new_break; 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) opline, &new_break, sizeof(phpdbg_breakline_t)); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong)(uintptr_t) opline, &new_break, sizeof(phpdbg_breakline_t)); 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); } } /* }}} */ @@ -1002,7 +1002,7 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_pt { phpdbg_breakline_t *brake; - if ((brake = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) && brake->base) { + if ((brake = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong)(uintptr_t) opline)) && brake->base) { return (phpdbg_breakbase_t *)brake->base; } @@ -1082,7 +1082,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)execute_data->opline == param->addr); } break; default: { diff --git a/sapi/phpdbg/phpdbg_btree.c b/sapi/phpdbg/phpdbg_btree.c index 81571c17c01a9..866789bfe40b8 100644 --- a/sapi/phpdbg/phpdbg_btree.c +++ b/sapi/phpdbg/phpdbg_btree.c @@ -250,7 +250,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, "%p: %p\n", (void *)(intptr_t) branch->result.idx, branch->result.ptr); } } } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 84bd7a076acec..609396881b930 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -591,7 +591,7 @@ int phpdbg_skip_line_helper(void) /* {{{ */ { || opline->opcode == ZEND_YIELD || opline->opcode == ZEND_YIELD_FROM ) { - zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong)(uintptr_t) opline, (void *) opline); } } while (++opline < op_array->opcodes + op_array->last); @@ -633,7 +633,7 @@ static void phpdbg_seek_to_end(void) /* {{{ */ { case ZEND_GENERATOR_RETURN: case ZEND_YIELD: case ZEND_YIELD_FROM: - zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong)(uintptr_t) opline, (void *) opline); } } while (++opline < op_array->opcodes + op_array->last); } @@ -647,7 +647,7 @@ PHPDBG_COMMAND(finish) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong)(uintptr_t) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); } else { PHPDBG_G(flags) |= PHPDBG_IN_FINISH; @@ -664,7 +664,7 @@ PHPDBG_COMMAND(leave) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong)(uintptr_t) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); phpdbg_notice("Already at the end of the function"); return SUCCESS; @@ -1713,7 +1713,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 4478dca0516ba..a014e2bfeb541 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -218,7 +218,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; @@ -301,7 +301,7 @@ int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context) { /* re-enable writing */ mprotect(page, phpdbg_pagesize, PROT_READ | PROT_WRITE); - zend_hash_index_add_empty_element(PHPDBG_G(watchlist_mem), (zend_ulong) page); + zend_hash_index_add_empty_element(PHPDBG_G(watchlist_mem), (zend_ulong)(uintptr_t) page); return SUCCESS; } @@ -317,7 +317,7 @@ void *phpdbg_watchpoint_userfaultfd_thread(void *phpdbg_globals_ptr) { struct uffd_msg fault_msg = {0}; while (read(globals->watch_userfaultfd, &fault_msg, sizeof(fault_msg)) == sizeof(fault_msg)) { void *page = phpdbg_get_page_boundary((char *)(uintptr_t) fault_msg.arg.pagefault.address); - zend_hash_index_add_empty_element(globals->watchlist_mem, (zend_ulong) page); + zend_hash_index_add_empty_element(globals->watchlist_mem, (zend_ulong)(uintptr_t) page); struct uffdio_writeprotect unprotect = { .mode = 0, .range = { @@ -335,14 +335,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 ### */ @@ -394,8 +394,8 @@ void phpdbg_watch_backup_data(phpdbg_watchpoint_t *watch) { /* watch collisions are responsible for having only one watcher on a given refcounted/refval and having a mapping back to the parent zvals */ void phpdbg_delete_watch_collision(phpdbg_watchpoint_t *watch) { phpdbg_watch_collision *coll; - if ((coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref))) { - zend_hash_index_del(&coll->parents, (zend_ulong) watch); + if ((coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref))) { + zend_hash_index_del(&coll->parents, (zend_ulong)(uintptr_t) watch); if (zend_hash_num_elements(&coll->parents) == 0) { phpdbg_remove_watchpoint_btree(&coll->ref); phpdbg_deactivate_watchpoint(&coll->ref); @@ -411,7 +411,7 @@ void phpdbg_delete_watch_collision(phpdbg_watchpoint_t *watch) { } } - zend_hash_index_del(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref); + zend_hash_index_del(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref); zend_hash_destroy(&coll->parents); efree(coll); } @@ -433,7 +433,7 @@ void phpdbg_update_watch_ref(phpdbg_watchpoint_t *watch) { watch->ref = Z_COUNTED_P(watch->addr.zv); - if (!(coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref))) { + if (!(coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref))) { coll = emalloc(sizeof(*coll)); coll->ref.type = WATCH_ON_REFCOUNTED; phpdbg_set_addr_watchpoint(Z_COUNTED_P(watch->addr.zv), sizeof(uint32_t), &coll->ref); @@ -462,9 +462,9 @@ void phpdbg_update_watch_ref(phpdbg_watchpoint_t *watch) { } zend_hash_init(&coll->parents, 8, NULL, NULL, 0); - zend_hash_index_add_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref, coll); + zend_hash_index_add_ptr(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref, coll); } - zend_hash_index_add_ptr(&coll->parents, (zend_long) watch, watch); + zend_hash_index_add_ptr(&coll->parents, (zend_long)(uintptr_t) watch, watch); } else if (Z_TYPE_P(watch->addr.zv) == IS_INDIRECT) { if ((zend_refcounted *) Z_INDIRECT_P(watch->addr.zv) == watch->ref) { return; @@ -476,7 +476,7 @@ void phpdbg_update_watch_ref(phpdbg_watchpoint_t *watch) { watch->ref = (zend_refcounted *) Z_INDIRECT_P(watch->addr.zv); - if (!(coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref))) { + if (!(coll = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref))) { coll = emalloc(sizeof(*coll)); phpdbg_set_zval_watchpoint(Z_INDIRECT_P(watch->addr.zv), &coll->ref); coll->ref.coll = coll; @@ -486,9 +486,9 @@ void phpdbg_update_watch_ref(phpdbg_watchpoint_t *watch) { phpdbg_watch_backup_data(&coll->ref); zend_hash_init(&coll->parents, 8, NULL, NULL, 0); - zend_hash_index_add_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->ref, coll); + zend_hash_index_add_ptr(&PHPDBG_G(watch_collisions), (zend_ulong)(uintptr_t) watch->ref, coll); } - zend_hash_index_add_ptr(&coll->parents, (zend_long) watch, watch); + zend_hash_index_add_ptr(&coll->parents, (zend_long)(uintptr_t) watch, watch); } else if (watch->ref) { phpdbg_delete_watch_collision(watch); watch->ref = NULL; @@ -505,7 +505,7 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element); phpdbg_watch_element *phpdbg_add_watch_element(phpdbg_watchpoint_t *watch, phpdbg_watch_element *element) { phpdbg_btree_result *res; - 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; @@ -647,12 +647,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; @@ -668,14 +668,14 @@ void phpdbg_watch_parent_ht(phpdbg_watch_element *element) { void phpdbg_unwatch_parent_ht(phpdbg_watch_element *element) { if (element->watch && element->watch->type == WATCH_ON_BUCKET) { - 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); if (res) { phpdbg_watch_ht_info *hti = res->ptr; 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); @@ -712,7 +712,7 @@ void phpdbg_queue_element_for_recreation(phpdbg_watch_element *element) { if (!element->parent) { /* HERE BE DRAGONS; i.e. we assume HashTable is directly allocated via emalloc() ... (which *should be* the case for every user-accessible array and symbol tables) */ - zend_hash_index_add_empty_element(&PHPDBG_G(watch_free), (zend_ulong) element->parent_container); + zend_hash_index_add_empty_element(&PHPDBG_G(watch_free), (zend_ulong)(uintptr_t) element->parent_container); } } @@ -775,7 +775,7 @@ void phpdbg_dequeue_elements_for_recreation(void) { ZEND_HASH_MAP_FOREACH_PTR(&PHPDBG_G(watch_recreation), element) { ZEND_ASSERT(element->flags & (PHPDBG_WATCH_IMPLICIT | PHPDBG_WATCH_RECURSIVE_ROOT | PHPDBG_WATCH_SIMPLE)); - if (element->parent || zend_hash_index_find(&PHPDBG_G(watch_free), (zend_ulong) element->parent_container)) { + if (element->parent || zend_hash_index_find(&PHPDBG_G(watch_free), (zend_ulong)(uintptr_t) element->parent_container)) { zval _zv, *zv = &_zv; if (element->parent) { ZEND_ASSERT(element->parent->watch->type == WATCH_ON_ZVAL || element->parent->watch->type == WATCH_ON_BUCKET); @@ -1019,7 +1019,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) { @@ -1132,7 +1132,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 *)(uintptr_t) page < (char *) watch->addr.ptr + watch->size) { #ifdef HAVE_USERFAULTFD_WRITEFAULT if (PHPDBG_G(watch_userfaultfd)) { struct uffdio_writeprotect protect = { @@ -1146,7 +1146,7 @@ void phpdbg_reenable_memory_watches(void) { } else #endif { - mprotect((void *) page, phpdbg_pagesize, PROT_READ); + mprotect((void *)(uintptr_t) page, phpdbg_pagesize, PROT_READ); } } } @@ -1179,7 +1179,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 *)(uintptr_t) page < (char *) watch->addr.ptr + watch->size) { phpdbg_check_watchpoint(watch); } } @@ -1206,7 +1206,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); @@ -1226,14 +1226,14 @@ 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); } } - zend_hash_index_del(&PHPDBG_G(watch_free), (zend_ulong) ptr); + zend_hash_index_del(&PHPDBG_G(watch_free), (zend_ulong)(uintptr_t) ptr); } if (PHPDBG_G(original_free_function)) { From a9ea53edccfd334d65754e177e169045155591c3 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 14:07:10 +0200 Subject: [PATCH 14/18] Fix ext/xml --- ext/xml/compat.c | 2 +- ext/xml/expat_compat.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/xml/compat.c b/ext/xml/compat.c index cafb19c2c1edd..48f0dc5883555 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -686,7 +686,7 @@ XML_GetCurrentColumnNumber(XML_Parser parser) return parser->parser->input->col; } -PHP_XML_API long +PHP_XML_API zend_long XML_GetCurrentByteIndex(XML_Parser parser) { return parser->parser->input->consumed + diff --git a/ext/xml/expat_compat.h b/ext/xml/expat_compat.h index 94ca8aeb4c351..812660aea5cca 100644 --- a/ext/xml/expat_compat.h +++ b/ext/xml/expat_compat.h @@ -146,7 +146,7 @@ PHP_XML_API int XML_GetErrorCode(XML_Parser); PHP_XML_API const XML_Char *XML_ErrorString(int); PHP_XML_API int XML_GetCurrentLineNumber(XML_Parser); PHP_XML_API int XML_GetCurrentColumnNumber(XML_Parser); -PHP_XML_API long XML_GetCurrentByteIndex(XML_Parser); +PHP_XML_API zend_long XML_GetCurrentByteIndex(XML_Parser); PHP_XML_API int XML_GetCurrentByteCount(XML_Parser); PHP_XML_API const XML_Char *XML_ExpatVersion(void); PHP_XML_API void XML_ParserFree(XML_Parser); From 85eea6dd6e6154adf85e68524ed180b64f625681 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 15:32:47 +0200 Subject: [PATCH 15/18] Fix ext/sysvmsg --- ext/sysvmsg/sysvmsg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c index 1f4cafd2bce0f..f77574975809d 100644 --- a/ext/sysvmsg/sysvmsg.c +++ b/ext/sysvmsg/sysvmsg.c @@ -34,12 +34,12 @@ PHP_MINFO_FUNCTION(sysvmsg); typedef struct { key_t key; - zend_long id; + int id; zend_object std; } sysvmsg_queue_t; struct php_msgbuf { - zend_long mtype; + size_t mtype; char mtext[1]; }; From 3a9145505c39e4f83d6b70d35d954dc0b24799a5 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 16:16:39 +0200 Subject: [PATCH 16/18] CFLAGS -mfpmath=sse --- .github/actions/configure-x32/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/configure-x32/action.yml b/.github/actions/configure-x32/action.yml index a5c5df4f7971d..9df639b7b58dd 100644 --- a/.github/actions/configure-x32/action.yml +++ b/.github/actions/configure-x32/action.yml @@ -12,8 +12,8 @@ runs: export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/lib/i386-linux-gnu/pkgconfig" ./buildconf --force - export CFLAGS="-m32 -msse2" - export CXXFLAGS="-m32 -msse2" + export CFLAGS="-m32 -msse2 -mfpmath=sse" + export CXXFLAGS="-m32 -msse2 -mfpmath=sse" export LDFLAGS=-L/usr/lib/i386-linux-gnu ./configure ${{ inputs.configurationParameters }} \ --enable-option-checking=fatal \ From 2220e7937fa87f204b70824b819222fda78a9cde Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Thu, 10 Jul 2025 22:30:12 +0200 Subject: [PATCH 17/18] Fix ext/calendar --- ext/calendar/easter.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/ext/calendar/easter.c b/ext/calendar/easter.c index 72c52e0fcff78..62b4652c3e75c 100644 --- a/ext/calendar/easter.c +++ b/ext/calendar/easter.c @@ -20,6 +20,7 @@ #include "php.h" #include "php_calendar.h" #include "sdncal.h" +#include "../date/lib/timelib.h" #include /** @@ -30,7 +31,7 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) { /* based on code by Simon Kershaw, */ - struct tm te; + timelib_time *t; zend_long year, golden, solar, lunar, pfm, dom, tmp, easter, result; zend_long method = CAL_EASTER_DEFAULT; const zend_long max_year = (zend_long)(ZEND_LONG_MAX / 5) * 4; @@ -59,7 +60,7 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) RETURN_THROWS(); } - #ifdef ZEND_ENABLE_ZVAL_LONG64 +#ifdef ZEND_ENABLE_ZVAL_LONG64 /* Compiling for 64bit, allow years between 1970 and 2.000.000.000 */ if (gm && year < 1970) { /* timestamps only start after 1970 */ @@ -72,13 +73,13 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) zend_argument_value_error(1, "must be a year before 2.000.000.000 (inclusive)"); RETURN_THROWS(); } - #else +#else /* Compiling for 32bit, allow years between 1970 and 2037 */ if (gm && (year < 1970 || year > 2037)) { zend_argument_value_error(1, "must be between 1970 and 2037 (inclusive)"); RETURN_THROWS(); } - #endif +#endif golden = (year % 19) + 1; /* the Golden number */ @@ -123,20 +124,26 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) easter = pfm + tmp + 1; /* Easter as the number of days after 21st March */ if (gm) { /* return a timestamp */ - te.tm_isdst = -1; - te.tm_year = year-1900; - te.tm_sec = 0; - te.tm_min = 0; - te.tm_hour = 0; + t = timelib_time_ctor(); + t->us = 0; + t->s = 0; + t->i = 0; + t->h = 0; + t->y = year; + t->z = 0; + t->dst = -1; if (easter < 11) { - te.tm_mon = 2; /* March */ - te.tm_mday = easter+21; + t->m = 3; + t->d = easter+21; } else { - te.tm_mon = 3; /* April */ - te.tm_mday = easter-10; + t->m = 4; + t->d = easter-10; } - result = mktime(&te); + + timelib_update_ts(t, NULL); + result = t->sse; + timelib_time_dtor(t); } else { /* return the days after March 21 */ result = easter; } From e28b7373612fa131f39c0ffad57bd57a167ac9b7 Mon Sep 17 00:00:00 2001 From: Marc Bennewitz Date: Fri, 11 Jul 2025 00:00:39 +0200 Subject: [PATCH 18/18] FIXME large file support -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES=1 --- .github/actions/configure-x32/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/configure-x32/action.yml b/.github/actions/configure-x32/action.yml index 9df639b7b58dd..172a6919e57ab 100644 --- a/.github/actions/configure-x32/action.yml +++ b/.github/actions/configure-x32/action.yml @@ -12,8 +12,8 @@ runs: export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/lib/i386-linux-gnu/pkgconfig" ./buildconf --force - export CFLAGS="-m32 -msse2 -mfpmath=sse" - export CXXFLAGS="-m32 -msse2 -mfpmath=sse" + export CFLAGS="-m32 -msse2 -mfpmath=sse -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES=1" + export CXXFLAGS="-m32 -msse2 -mfpmath=sse -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES=1" export LDFLAGS=-L/usr/lib/i386-linux-gnu ./configure ${{ inputs.configurationParameters }} \ --enable-option-checking=fatal \