Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2f2fb1f
Skip lc_ctype_inheritance.phpt on macos 15+
shivammathur Oct 13, 2025
9a2113a
Disable inlining and inter-procedure-analyses for zend_string_equal_v…
dstogov Jan 9, 2024
c2fd6d6
Merge branch 'PHP-8.1' into PHP-8.2
iluuu1994 Oct 15, 2025
ff3a12b
Merge branch 'PHP-8.2' into PHP-8.3
iluuu1994 Oct 15, 2025
4b0ad46
Merge branch 'PHP-8.3' into PHP-8.4
iluuu1994 Oct 15, 2025
d63be3f
Merge branch 'PHP-8.4' into PHP-8.5
iluuu1994 Oct 15, 2025
cfcfc6f
Merge branch 'PHP-8.5'
iluuu1994 Oct 15, 2025
e3e37c8
Upgrade nightly macOS version to macos 15 (#20159)
shivammathur Oct 15, 2025
56af25c
exif: Fix possible memory leak when tag is empty
nielsdos Oct 14, 2025
d1018be
Merge branch 'PHP-8.3' into PHP-8.4
nielsdos Oct 15, 2025
f238665
Merge branch 'PHP-8.4' into PHP-8.5
nielsdos Oct 15, 2025
108b90d
Merge branch 'PHP-8.5'
nielsdos Oct 15, 2025
472f2fe
Fix GH-8978: MySQLi: SSL certificate verification fails (port doubled)
nielsdos Sep 30, 2025
aa82c9c
Merge branch 'PHP-8.3' into PHP-8.4
nielsdos Oct 15, 2025
dd60911
Merge branch 'PHP-8.4' into PHP-8.5
nielsdos Oct 15, 2025
f9678e7
Merge branch 'PHP-8.5'
nielsdos Oct 15, 2025
bbe2191
ROR the callable_convert_cache key for better hash distribution (#20052)
nielsdos Oct 15, 2025
94625a0
Fix GH-19722: Windows: _get_osfhandle asserts in debug mode when give…
dktapps Sep 5, 2025
8dd117f
Merge branch 'PHP-8.3' into PHP-8.4
nielsdos Oct 15, 2025
0ef96a2
Merge branch 'PHP-8.4' into PHP-8.5
nielsdos Oct 15, 2025
8dc1a3d
Merge branch 'PHP-8.5'
nielsdos Oct 15, 2025
a3cf188
ext/phar: use %zu printf specifier for size_t
Girgias Oct 13, 2025
ebbe64b
ext/phar: use uint32_t type instead of int
Girgias Oct 13, 2025
68b419a
ext/phar: use zend_result type instead of int
Girgias Oct 13, 2025
2e62399
ext/phar: use bool type instead of int
Girgias Oct 13, 2025
75c1c32
ext/phar: Return const char* as these are in the rodata section
Girgias Oct 13, 2025
a5f6165
ext/phar: use bool type instead of uint32_t
Girgias Oct 13, 2025
453f9e1
ext/phar: pad phar globals struct
Girgias Oct 13, 2025
6e6752f
ext/phar: pad _phar_entry_info struct
Girgias Oct 13, 2025
fb81bdd
ext/phar: pad _phar_archive_data struct
Girgias Oct 13, 2025
bf44b6e
ext/phar/phar.c: use zend_hash_str_exists() instead of fetching ptr a…
Girgias Oct 13, 2025
264d650
ext/phar/phar_object.c: Refactor extraction code to use zend_string*
Girgias Oct 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ on:
libmysqlclient_with_mysqli:
required: true
type: boolean
macos_arm64_version:
required: true
type: string
run_alpine:
required: true
type: boolean
Expand Down Expand Up @@ -366,11 +369,11 @@ jobs:
matrix:
debug: [true, false]
zts: [true, false]
os: ['13', '14']
arch: ['X64', 'ARM64']
exclude:
- os: ${{ !inputs.run_macos_arm64 && '14' || '*never*' }}
name: "MACOS_${{ matrix.os == '13' && 'X64' || 'ARM64' }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
runs-on: macos-${{ matrix.os }}
- arch: ${{ !inputs.run_macos_arm64 && 'ARM64' || '*never*' }}
name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}"
runs-on: macos-${{ matrix.arch == 'X64' && '15-intel' || inputs.macos_arm64_version }}
steps:
- name: git checkout
uses: actions/checkout@v5
Expand All @@ -393,7 +396,7 @@ jobs:
- name: Test
uses: ./.github/actions/test-macos
- name: Test Tracing JIT
if: matrix.os != '14' || !matrix.zts
if: matrix.arch == 'X64' || !matrix.zts
uses: ./.github/actions/test-macos
with:
jitType: tracing
Expand All @@ -405,7 +408,7 @@ jobs:
runTestsParameters: >-
-d opcache.enable_cli=1
- name: Test Function JIT
if: matrix.os != '14' || !matrix.zts
if: matrix.arch == 'X64' || !matrix.zts
uses: ./.github/actions/test-macos
with:
jitType: function
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/root.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
branch: ${{ matrix.branch.ref }}
community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }}
macos_arm64_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '15' || '14' }}
run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
run_linux_ppc64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }}
Expand Down
6 changes: 5 additions & 1 deletion Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -9720,7 +9720,11 @@ ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED, NUM|CACHE_SLOT)
if (closure) {
ZVAL_OBJ_COPY(EX_VAR(opline->result.var), closure);
} else {
zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), (zend_ulong)(uintptr_t)call->func);
/* Rotate the key for better hash distribution. */
const int shift = sizeof(size_t) == 4 ? 6 : 7;
zend_ulong key = (zend_ulong)(uintptr_t)call->func;
key = (key >> shift) | (key << ((sizeof(key) * 8) - shift));
zval *closure_zv = zend_hash_index_lookup(&EG(callable_convert_cache), key);
if (Z_TYPE_P(closure_zv) == IS_NULL) {
zend_closure_from_frame(closure_zv, call);
}
Expand Down
12 changes: 10 additions & 2 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion ext/ctype/tests/lc_ctype_inheritance.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Do not inherit LC_CTYPE from environment
ctype
--SKIPIF--
<?php
if (PHP_OS_FAMILY === 'Darwin') die('skip Fails for macOS 15');
if (PHP_OS_FAMILY === 'Darwin' && version_compare(php_uname('r'), '24.0.0', '>=')) {
die('skip macOS 15 inherits LC_CTYPE into the thread locale');
}
if (setlocale(LC_ALL, 'invalid') === 'invalid') { die('skip setlocale() is broken /w musl'); }
if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale");
?>
Expand Down
1 change: 1 addition & 0 deletions ext/exif/exif.c
Original file line number Diff line number Diff line change
Expand Up @@ -3261,6 +3261,7 @@ static bool exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * val

#define REQUIRE_NON_EMPTY() do { \
if (byte_count == 0) { \
EFREE_IF(outside); \
exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Cannot be empty", tag, exif_get_tagname_debug(tag, tag_table)); \
return false; \
} \
Expand Down
9 changes: 8 additions & 1 deletion ext/mysqlnd/mysqlnd_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_
if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) {
transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port);
} else {
transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port);
/* Not ipv6, but could already contain a port number, in which case we should not add an extra port.
* See GH-8978. In a port doubling scenario, the first port would be used so we do the same to keep BC. */
if (strchr(hostname.s, ':')) {
/* TODO: Ideally we should be able to get rid of this workaround in the future. */
transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s", hostname.s);
} else {
transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port);
}
}
}
DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM");
Expand Down
6 changes: 3 additions & 3 deletions ext/phar/dirstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
return 0;
}

if ((e = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 2, &error, 1))) {
if ((e = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 2, &error, true))) {
/* directory exists, or is a subdirectory of an existing file */
if (e->is_temp_dir) {
zend_string_efree(e->filename);
Expand All @@ -412,7 +412,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
return 0;
}

if (phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 0, &error, 1)) {
if (phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, ZSTR_LEN(resource->path) - 1, 0, &error, true)) {
/* entry exists as a file */
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host));
php_url_free(resource);
Expand Down Expand Up @@ -523,7 +523,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options

size_t path_len = ZSTR_LEN(resource->path) - 1;

if (!(entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, 1))) {
if (!(entry = phar_get_entry_info_dir(phar, ZSTR_VAL(resource->path) + 1, path_len, 2, &error, true))) {
if (error) {
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error);
efree(error);
Expand Down
49 changes: 24 additions & 25 deletions ext/phar/phar.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,6 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al
&& ((alias && fname_len == phar->fname_len
&& !strncmp(fname, phar->fname, fname_len)) || !alias)
) {
phar_entry_info *stub;
#ifdef PHP_WIN32
if (fname != save_fname) {
free_alloca(fname, fname_use_heap);
Expand All @@ -526,7 +525,7 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al
if (!is_data) {
/* prevent any ".phar" without a stub getting through */
if (!phar->halt_offset && !phar->is_brandnew && (phar->is_tar || phar->is_zip)) {
if (PHAR_G(readonly) && NULL == (stub = zend_hash_str_find_ptr(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
if (PHAR_G(readonly) && !zend_hash_str_exists(&(phar->manifest), ZEND_STRL(".phar/stub.php"))) {
if (error) {
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
}
Expand Down Expand Up @@ -736,7 +735,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname
uint32_t len;
zend_long offset;
size_t sig_len;
int register_alias = 0, temp_alias = 0;
bool register_alias = false, temp_alias = false;
char *signature = NULL;
zend_string *str;

Expand Down Expand Up @@ -1069,15 +1068,15 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname
alias_len = tmp_len;
alias = buffer;
buffer += tmp_len;
register_alias = 1;
register_alias = true;
} else if (!alias_len || !alias) {
/* if we neither have an explicit nor an implicit alias, we use the filename */
alias = NULL;
alias_len = 0;
register_alias = 0;
register_alias = false;
} else if (alias_len) {
register_alias = 1;
temp_alias = 1;
register_alias = true;
temp_alias = true;
}

/* we have 5 32-bit items plus 1 byte at least */
Expand Down Expand Up @@ -1325,12 +1324,12 @@ zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *al
}

/* first try to open an existing file */
if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1) == SUCCESS) {
if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, true) == SUCCESS) {
goto check_file;
}

/* next try to create a new file */
if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1)) {
if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, true)) {
if (error) {
if (ext_len == -2) {
spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname);
Expand All @@ -1354,8 +1353,7 @@ zend_result phar_open_or_create_filename(char *fname, size_t fname_len, char *al
}

if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
phar_entry_info *stub;
if (NULL == (stub = zend_hash_str_find_ptr(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
if (!zend_hash_str_exists(&((*test)->manifest), ZEND_STRL(".phar/stub.php"))) {
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
return FAILURE;
}
Expand Down Expand Up @@ -1970,7 +1968,7 @@ static zend_result phar_check_str(const char *fname, const char *ext_str, size_t
* the last parameter should be set to tell the thing to assume that filename is the full path, and only to check the
* extension rules, not to iterate.
*/
zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, int is_complete) /* {{{ */
zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete) /* {{{ */
{
const char *pos, *slash;

Expand Down Expand Up @@ -2131,7 +2129,7 @@ static bool php_check_dots(const char *element, size_t n) /* {{{ */
/**
* Remove .. and . references within a phar filename
*/
char *phar_fix_filepath(char *path, size_t *new_len, int use_cwd) /* {{{ */
char *phar_fix_filepath(char *path, size_t *new_len, bool use_cwd) /* {{{ */
{
char *newpath;
size_t newpath_len;
Expand Down Expand Up @@ -2268,7 +2266,7 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a
phar_unixify_path_separators((char *)filename, filename_len);
}
#endif
if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, 0) == FAILURE) {
if (phar_detect_phar_fname_ext(filename, filename_len, &ext_str, &ext_len, executable, for_create, false) == FAILURE) {
if (ext_len != -1) {
if (!ext_str) {
/* no / detected, restore arch for error message */
Expand Down Expand Up @@ -2544,7 +2542,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa

phar_entry_info *entry, *newentry;
size_t halt_offset;
int restore_alias_len, global_flags = 0;
uint32_t restore_alias_len;
uint32_t global_flags = 0;
bool must_close_old_file = false;
bool has_dirs = false;
char manifest[18], entry_buffer[24];
Expand Down Expand Up @@ -2747,7 +2746,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa
}
continue;
}
if (!phar_get_efp(entry, 0)) {
if (!phar_get_efp(entry, false)) {
/* re-open internal file pointer just-in-time */
newentry = phar_open_jit(phar, entry, error);
if (!newentry) {
Expand All @@ -2758,8 +2757,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa
}
entry = newentry;
}
file = phar_get_efp(entry, 0);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1)) {
file = phar_get_efp(entry, false);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, true)) {
if (must_close_old_file) {
php_stream_close(oldfile);
}
Expand All @@ -2778,7 +2777,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa
entry->compressed_filesize = entry->uncompressed_filesize;
continue;
}
filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0);
filter = php_stream_filter_create(phar_compress_filter(entry, false), NULL, 0);
if (!filter) {
if (must_close_old_file) {
php_stream_close(oldfile);
Expand Down Expand Up @@ -2818,7 +2817,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa
ZEND_ASSERT(entry->header_offset == 0);
entry->header_offset = php_stream_tell(entry->cfp);
php_stream_flush(file);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) {
php_stream_filter_free(filter);
if (must_close_old_file) {
php_stream_close(oldfile);
Expand Down Expand Up @@ -3024,8 +3023,8 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa
file = entry->cfp;
php_stream_seek(file, entry->header_offset, SEEK_SET);
} else {
file = phar_get_efp(entry, 0);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
file = phar_get_efp(entry, false);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, false)) {
if (must_close_old_file) {
php_stream_close(oldfile);
}
Expand Down Expand Up @@ -3267,7 +3266,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type)
{
zend_op_array *res;
zend_string *name = NULL;
int failed;
bool failed;
phar_archive_data *phar;

if (!file_handle || !file_handle->filename) {
Expand Down Expand Up @@ -3318,11 +3317,11 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type)
}

zend_try {
failed = 0;
failed = false;
CG(zend_lineno) = 0;
res = phar_orig_compile_file(file_handle, type);
} zend_catch {
failed = 1;
failed = true;
res = NULL;
} zend_end_try();

Expand Down
Loading