From 3620667bd2fe05d0bc0553cd00007d260ff8d6da Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Tue, 28 Jul 2026 17:31:12 +0200 Subject: [PATCH 1/9] [ci skip] Moved NEWS entry Commit happened between after tagging alpha3, but before pushing to the repo --- NEWS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7d85ff104dcd..ebba48ca7037 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.6.0beta1 +- GMP: + . Added gmp_powm_sec(). (Weilin Du) 30 Jul 2026, PHP 8.6.0alpha3 @@ -23,7 +25,6 @@ PHP NEWS . Made php-cli functionality available in embed builds. (henderkes) - GMP: - . Added gmp_powm_sec(). (Weilin Du) . Added gmp_prevprime(). (Weilin Du, David Carlier) . Fixed GMP power and shift operators to reject GMP right operands outside the unsigned long range instead of silently truncating them. (Weilin Du) From 9518d49da0f56aa806a8c4c0e364de2802bf6bcf Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 28 Jul 2026 17:29:11 +0100 Subject: [PATCH 2/9] Zend: add _ex variants for calling known functions/FCC (#22910) To permit setting the consumed_arg FCI field --- Zend/zend_API.h | 23 ++++++++++++++++++----- Zend/zend_execute_API.c | 6 +++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 2c0b892d1941..622e90da59b2 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -854,12 +854,19 @@ static zend_always_inline zend_result zend_call_function_with_return_value( * If retval_ptr is NULL, the return value is discarded. * If object is NULL, this must be a free function or static call. * called_scope must be provided for instance and static method calls. */ -ZEND_API void zend_call_known_function( +ZEND_API void zend_call_known_function_ex( zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, - uint32_t param_count, zval *params, HashTable *named_params); + uint32_t param_count, zval *params, HashTable *named_params, uint32_t consumed_args); -static zend_always_inline void zend_call_known_fcc( - const zend_fcall_info_cache *fcc, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params) +static zend_always_inline void zend_call_known_function( + zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, + uint32_t param_count, zval *params, HashTable *named_params) { + zend_call_known_function_ex(fn, object, called_scope, retval_ptr, param_count, params, named_params, 0); +} + +static zend_always_inline void zend_call_known_fcc_ex( + const zend_fcall_info_cache *fcc, zval *retval_ptr, + uint32_t param_count, zval *params, HashTable *named_params, uint32_t consumed_args) { zend_function *func = fcc->function_handler; /* Need to copy trampolines as they get released after they are called */ @@ -868,7 +875,13 @@ static zend_always_inline void zend_call_known_fcc( memcpy(func, fcc->function_handler, sizeof(zend_function)); zend_string_addref(func->op_array.function_name); } - zend_call_known_function(func, fcc->object, fcc->called_scope, retval_ptr, param_count, params, named_params); + zend_call_known_function_ex(func, fcc->object, fcc->called_scope, retval_ptr, param_count, params, named_params, consumed_args); +} + +static zend_always_inline void zend_call_known_fcc( + const zend_fcall_info_cache *fcc, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params) +{ + zend_call_known_fcc_ex(fcc, retval_ptr, param_count, params, named_params, 0); } /* Call the provided zend_function instance method on an object. */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 88b0a485750a..83ba5e7490cf 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1100,9 +1100,9 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ } /* }}} */ -ZEND_API void zend_call_known_function( +ZEND_API void zend_call_known_function_ex( zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, - uint32_t param_count, zval *params, HashTable *named_params) + uint32_t param_count, zval *params, HashTable *named_params, uint32_t consumed_args) { zval retval; zend_fcall_info fci; @@ -1116,7 +1116,7 @@ ZEND_API void zend_call_known_function( fci.param_count = param_count; fci.params = params; fci.named_params = named_params; - fci.consumed_args = 0; + fci.consumed_args = consumed_args; ZVAL_UNDEF(&fci.function_name); /* Unused */ fcic.function_handler = fn; From a652a00c02a4d7aa5bb6f7939aa2628b64dfbad5 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 28 Jul 2026 18:29:39 +0200 Subject: [PATCH 3/9] Follow-up GH-22829 --- Zend/Optimizer/dfa_pass.c | 2 +- Zend/tests/partial_application/const_arg_opt.phpt | 12 ++++++------ Zend/zend_ast.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index dcb4e8bc8412..8826ca41641f 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -471,7 +471,7 @@ static uint32_t zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) } if (call_info->caller_call_opline && call_info->caller_call_opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) { - /* Build a bitset of constant pre-bound PFA args: These are args whose value is alway the same for all + /* Build a bitset of constant pre-bound PFA args: These are args whose value is always the same for all * instances of a PFA. */ uint32_t const_args = 0; for (uint32_t i = 0, l = MIN(sizeof(const_args)*CHAR_BIT, call_info->num_args); i < l; i++) { diff --git a/Zend/tests/partial_application/const_arg_opt.phpt b/Zend/tests/partial_application/const_arg_opt.phpt index d63456a96a5d..4b3afd1c2d2a 100644 --- a/Zend/tests/partial_application/const_arg_opt.phpt +++ b/Zend/tests/partial_application/const_arg_opt.phpt @@ -46,12 +46,12 @@ $f(2); echo "# Constant pre-bound argument:\n"; $f = f(2, ?); print_lexical_vars($f); -$f(2); +$f(1); echo "# Constant pre-bound argument (inverted):\n"; -$f = f(?, 2); +$f = f(?, 3); print_lexical_vars($f); -$f(1); +$f(4); echo "# Inlined pre-bound argument:\n"; $f = f(g(), ?); @@ -100,15 +100,15 @@ array(2) { [0]=> int(2) [1]=> - int(2) + int(1) } # Constant pre-bound argument (inverted): no lexical vars array(2) { [0]=> - int(1) + int(4) [1]=> - int(2) + int(3) } # Inlined pre-bound argument: no lexical vars diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index a17cb3d91b91..a91f0d2c933a 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1352,7 +1352,7 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( ZEND_CALL_NUM_ARGS(frame), ZEND_CALL_ARG(frame, 1), extra_named_params, named_positions, fcc_ast->filename, &ast->lineno, - (void**)cache_slot, fcc_ast->name, flags, 0); + (void**)cache_slot, fcc_ast->name, flags, /* const_args */ 0); if (named_positions) { zend_array_release(named_positions); From bcb05dcf6f31f6345e3cf21bd1242e40df7f68e1 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 28 Jul 2026 12:59:27 +0100 Subject: [PATCH 4/9] zip: convert ZIP option remove_path to zend_string* --- ext/zip/php_zip.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 33b0dadb900f..a35b7d5aaf9f 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -353,8 +353,7 @@ static zend_result php_zip_add_file(ze_zip_object *obj, const char *filename, si typedef struct { zend_long remove_all_path; - char *remove_path; - size_t remove_path_len; + const zend_string *remove_path; char *add_path; size_t add_path_len; zip_flags_t flags; @@ -450,8 +449,8 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts) zend_value_error("Option \"remove_path\" must be less than %d bytes", MAXPATHLEN - 1); return FAILURE; } - opts->remove_path_len = Z_STRLEN_P(option); - opts->remove_path = Z_STRVAL_P(option); + /* No need to copy the string as it's only ever used to check the paths after parsing the options */ + opts->remove_path = Z_STR_P(option); } if ((option = zend_hash_str_find(options, "add_path", sizeof("add_path") - 1)) != NULL) { @@ -1836,13 +1835,13 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); file_stripped_len = ZSTR_LEN(basename); - } else if (opts.remove_path && Z_STRLEN_P(zval_file) > opts.remove_path_len && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { - if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) { - file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1; - file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1; + } else if (opts.remove_path && zend_string_starts_with(Z_STR_P(zval_file), opts.remove_path)) { + if (IS_SLASH(Z_STRVAL_P(zval_file)[ZSTR_LEN(opts.remove_path)])) { + file_stripped = Z_STRVAL_P(zval_file) + ZSTR_LEN(opts.remove_path) + 1; + file_stripped_len = Z_STRLEN_P(zval_file) - ZSTR_LEN(opts.remove_path) - 1; } else { - file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len; - file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len; + file_stripped = Z_STRVAL_P(zval_file) + ZSTR_LEN(opts.remove_path); + file_stripped_len = Z_STRLEN_P(zval_file) - ZSTR_LEN(opts.remove_path); } } else { file_stripped = Z_STRVAL_P(zval_file); From 0d440d3768031e1405d83343bb0d01374ef10d4d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 28 Jul 2026 13:06:23 +0100 Subject: [PATCH 5/9] zip: convert ZIP option add_path to zend_string* --- ext/zip/php_zip.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index a35b7d5aaf9f..2e1e8dc86251 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -354,8 +354,7 @@ static zend_result php_zip_add_file(ze_zip_object *obj, const char *filename, si typedef struct { zend_long remove_all_path; const zend_string *remove_path; - char *add_path; - size_t add_path_len; + const zend_string *add_path; zip_flags_t flags; zip_int32_t comp_method; zip_uint32_t comp_flags; @@ -469,8 +468,7 @@ static zend_result php_zip_parse_options(HashTable *options, zip_options *opts) zend_value_error("Option \"add_path\" must be less than %d bytes", MAXPATHLEN - 1); return FAILURE; } - opts->add_path_len = Z_STRLEN_P(option); - opts->add_path = Z_STRVAL_P(option); + opts->add_path = Z_STR_P(option); } if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) { @@ -1849,16 +1847,16 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* } if (opts.add_path) { - if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) { + if ((ZSTR_LEN(opts.add_path) + file_stripped_len) > MAXPATHLEN) { if (basename) { zend_string_release_ex(basename, false); } - php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)", - MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len)); + php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zu given)", + MAXPATHLEN - 1, (ZSTR_LEN(opts.add_path) + file_stripped_len)); zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } - snprintf(entry_name_buf, MAXPATHLEN, "%s%s", opts.add_path, file_stripped); + snprintf(entry_name_buf, MAXPATHLEN, "%s%s", ZSTR_VAL(opts.add_path), file_stripped); } else { snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped); } From 6739acedc8209058782e74c3afc01c0184144373 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 28 Jul 2026 13:24:10 +0100 Subject: [PATCH 6/9] zip: add static storage specifier for private functions --- ext/zip/php_zip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 2e1e8dc86251..6f0b8e96c56f 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -651,7 +651,7 @@ static bool php_zipobj_close(ze_zip_object *obj, zend_string **out_str) /* {{{ * } /* }}} */ -int php_zip_glob(zend_string *spattern, zend_long flags, zval *return_value) /* {{{ */ +static int php_zip_glob(zend_string *spattern, zend_long flags, zval *return_value) /* {{{ */ { int cwd_skip = 0; #ifdef ZTS @@ -755,7 +755,7 @@ int php_zip_glob(zend_string *spattern, zend_long flags, zval *return_value) /* } /* }}} */ -int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value) /* {{{ */ +static int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value) /* {{{ */ { #ifdef ZTS char cwd[MAXPATHLEN]; From 73e3e054e2c1b94eef991d3abb05f02be18df951 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Tue, 28 Jul 2026 13:18:11 +0100 Subject: [PATCH 7/9] zip: use zend_string* to build entry_name --- ext/zip/php_zip.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 6f0b8e96c56f..06bd6691be13 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1823,12 +1823,11 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* ze_zip_object *ze_obj = Z_ZIP_P(self); for (int i = 0; i < found; i++) { - char *file_stripped, *entry_name; - size_t entry_name_len, file_stripped_len; - char entry_name_buf[MAXPATHLEN]; zend_string *basename = NULL; if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(return_value), i)) != NULL) { + const char *file_stripped; + size_t file_stripped_len; if (opts.remove_all_path) { basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); @@ -1846,6 +1845,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* file_stripped_len = Z_STRLEN_P(zval_file); } + zend_string *entry_name; if (opts.add_path) { if ((ZSTR_LEN(opts.add_path) + file_stripped_len) > MAXPATHLEN) { if (basename) { @@ -1856,20 +1856,25 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } - snprintf(entry_name_buf, MAXPATHLEN, "%s%s", ZSTR_VAL(opts.add_path), file_stripped); + entry_name = zend_string_concat2( + ZSTR_VAL(opts.add_path), ZSTR_LEN(opts.add_path), + file_stripped, file_stripped_len + ); } else { - snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped); + entry_name = zend_string_init(file_stripped, file_stripped_len, false); } + ZEND_ASSERT(ZSTR_LEN(entry_name) <= MAXPATHLEN); - entry_name = entry_name_buf; - entry_name_len = strlen(entry_name); if (basename) { zend_string_release_ex(basename, false); basename = NULL; } - if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), - entry_name, entry_name_len, 0, 0, -1, opts.flags) == FAILURE) { + const zend_result status = php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), + ZSTR_VAL(entry_name), ZSTR_LEN(entry_name), 0, 0, -1, opts.flags); + + zend_string_release_ex(entry_name, false); + if (status == FAILURE) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } From 534bcd20353ce9cfd31f88d33712ccb34ee054ed Mon Sep 17 00:00:00 2001 From: Eric Mann Date: Tue, 28 Jul 2026 11:11:32 -0700 Subject: [PATCH 8/9] PHP-8.3 is now for PHP 8.3.34-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 875982a3eb9a..48d2e2083933 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.33 +?? ??? ????, PHP 8.3.34 + + +30 Jul 2026, PHP 8.3.33 - Date: . Fixed leak on double DatePeriod::__construct() call. (ilutov) diff --git a/Zend/zend.h b/Zend/zend.h index e022b97a663d..cd91eb9f00bb 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.33-dev" +#define ZEND_VERSION "4.3.34-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index f85650811327..9ed44d6cfb63 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.3.33-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.34-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index df3ccaf05352..7943f1295258 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 3 -#define PHP_RELEASE_VERSION 33 +#define PHP_RELEASE_VERSION 34 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.33-dev" -#define PHP_VERSION_ID 80333 +#define PHP_VERSION "8.3.34-dev" +#define PHP_VERSION_ID 80334 From 645966449554ac7c048125b01616358327277bd8 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 29 Jul 2026 03:09:44 +0800 Subject: [PATCH 9/9] ext/gmp: expose the possibility of being a prime in `gmp_prevprime` (#22907) Follow up #22807 to expose the "definitelyPrime" parameter in the gmp_prevprime function to indicate the possibility of whether the outputted number is actually a prime. --- NEWS | 2 ++ UPGRADING | 8 +++++--- ext/gmp/gmp.c | 8 +++++++- ext/gmp/gmp.stub.php | 3 ++- ext/gmp/gmp_arginfo.h | 3 ++- ext/gmp/tests/gmp_prevprime.phpt | 26 ++++++++++++++++++++++++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index ebba48ca7037..0c2fd04ad469 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? ????, PHP 8.6.0beta1 - GMP: + . Added optional $definitely_prime output parameter to gmp_prevprime(). + (Weilin Du) . Added gmp_powm_sec(). (Weilin Du) 30 Jul 2026, PHP 8.6.0alpha3 diff --git a/UPGRADING b/UPGRADING index 7c9473d07b7d..d8c8a953766a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -275,9 +275,11 @@ PHP 8.6 UPGRADE NOTES . Added gmp_powm_sec() for side-channel quiet modular exponentiation. Requires GNU MP 5.0.0 or later. . Added gmp_prevprime() to get the largest prime smaller than the given - number. A ValueError is thrown if no such prime exists. This function is - available only when PHP is built against GNU MP 6.3.0 or later; it is not - available on official Windows builds using MPIR. + number. The optional $definitely_prime output parameter indicates whether + the returned number is definitely prime, as opposed to probably prime. + A ValueError is thrown if no such prime exists. This function is available + only when PHP is built against GNU MP 6.3.0 or later; it is not available + on official Windows builds using MPIR. - Intl: . Added Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue(), diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index bf0a77666b6f..4a81026d451b 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1087,10 +1087,13 @@ GMP_UNARY_OP_FUNCTION(nextprime); ZEND_FUNCTION(gmp_prevprime) { mpz_ptr gmpnum_a, gmpnum_result; + zval *definitely_prime = NULL; int res; - ZEND_PARSE_PARAMETERS_START(1, 1) + ZEND_PARSE_PARAMETERS_START(1, 2) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_a) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(definitely_prime) ZEND_PARSE_PARAMETERS_END(); if (mpz_cmp_ui(gmpnum_a, 2) <= 0) { @@ -1106,6 +1109,9 @@ ZEND_FUNCTION(gmp_prevprime) INIT_GMP_RETVAL(gmpnum_result); res = mpz_prevprime(gmpnum_result, gmpnum_a); ZEND_ASSERT(res); + if (definitely_prime) { + ZEND_TRY_ASSIGN_REF_BOOL(definitely_prime, res == 2); + } } /* }}} */ #endif diff --git a/ext/gmp/gmp.stub.php b/ext/gmp/gmp.stub.php index f2ea15481748..e9c3d51ad41d 100644 --- a/ext/gmp/gmp.stub.php +++ b/ext/gmp/gmp.stub.php @@ -188,7 +188,8 @@ function gmp_hamdist(GMP|int|string $num1, GMP|int|string $num2): int {} function gmp_nextprime(GMP|int|string $num): GMP {} #ifdef HAVE___GMPZ_PREVPRIME -function gmp_prevprime(GMP|int|string $num): GMP {} +/** @param bool $definitely_prime */ +function gmp_prevprime(GMP|int|string $num, &$definitely_prime = null): GMP {} #endif function gmp_binomial(GMP|int|string $n, int $k): GMP {} diff --git a/ext/gmp/gmp_arginfo.h b/ext/gmp/gmp_arginfo.h index 60eec94bb5cf..dddaa7e528c9 100644 --- a/ext/gmp/gmp_arginfo.h +++ b/ext/gmp/gmp_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit gmp.stub.php instead. - * Stub hash: 57d016aed930bb41ff4357917e3ae8abd612e973 */ + * Stub hash: 743a4be1078abfa29294336564126ace8c194cbe */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_gmp_init, 0, 1, GMP, 0) ZEND_ARG_TYPE_MASK(0, num, MAY_BE_LONG|MAY_BE_STRING, NULL) @@ -190,6 +190,7 @@ ZEND_END_ARG_INFO() #if defined(HAVE___GMPZ_PREVPRIME) ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_gmp_prevprime, 0, 1, GMP, 0) ZEND_ARG_OBJ_TYPE_MASK(0, num, GMP, MAY_BE_LONG|MAY_BE_STRING, NULL) + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, definitely_prime, "null") ZEND_END_ARG_INFO() #endif diff --git a/ext/gmp/tests/gmp_prevprime.phpt b/ext/gmp/tests/gmp_prevprime.phpt index 42c08566c413..541a62f918d5 100644 --- a/ext/gmp/tests/gmp_prevprime.phpt +++ b/ext/gmp/tests/gmp_prevprime.phpt @@ -19,16 +19,42 @@ foreach ([-1, 0, 1, 2] as $value) { } } +$definitelyPrime = null; +try { + var_dump(gmp_prevprime(2, $definitelyPrime)); +} catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; +} +var_dump($definitelyPrime); + var_dump(gmp_strval(gmp_prevprime(3))); var_dump(gmp_strval(gmp_prevprime(4))); var_dump(gmp_strval(gmp_prevprime(10000))); +$definitelyPrime = null; +var_dump(gmp_strval(gmp_prevprime(3, $definitelyPrime))); +var_dump($definitelyPrime); + +$probablePrime = gmp_nextprime(gmp_pow(10, 80)); +$definitelyPrime = null; +$previousPrime = gmp_prevprime(gmp_add($probablePrime, 1), $definitelyPrime); +var_dump(gmp_cmp($previousPrime, $probablePrime) === 0); +var_dump(is_bool($definitelyPrime)); +var_dump($definitelyPrime === (gmp_prob_prime($previousPrime) === 2)); + ?> --EXPECT-- gmp_prevprime(): Argument #1 ($num) must be greater than 2 gmp_prevprime(): Argument #1 ($num) must be greater than 2 gmp_prevprime(): Argument #1 ($num) must be greater than 2 gmp_prevprime(): Argument #1 ($num) must be greater than 2 +gmp_prevprime(): Argument #1 ($num) must be greater than 2 +NULL string(1) "2" string(1) "3" string(4) "9973" +string(1) "2" +bool(true) +bool(true) +bool(true) +bool(true)