diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml index b318f22725150..f0af959d21026 100644 --- a/.github/actions/configure-macos/action.yml +++ b/.github/actions/configure-macos/action.yml @@ -11,7 +11,7 @@ runs: set -x BREW_OPT="$(brew --prefix)"/opt export PATH="$BREW_OPT/bison/bin:$PATH" - export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/openssl@1.1/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/openssl/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/curl/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/libffi/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/libxml2/lib/pkgconfig" diff --git a/NEWS b/NEWS index 1984a4a81dc52..7e3bdb8c71acf 100644 --- a/NEWS +++ b/NEWS @@ -5,9 +5,16 @@ PHP NEWS - Core: . Destructing non-array values (other than NULL) using [] or list() now emits a warning. (Girgias) + . Fixed bug GH-19637 (Incorrect Closure scope for FCC in constant + expression). (timwolla) + +- EXIF: + . Added support to retrieve Exif from HEIF file. (Benstone Zhang) - Opcache: . Fixed bug GH-19486 (Incorrect opline after deoptimization). (Arnaud) + . Fixed bug GH-19601 (Wrong JIT stack setup on aarch64/clang). (Arnaud) + . Fixed bug GH-19388 (Broken opcache.huge_code_pages). (Arnaud) - PCRE: . Upgraded to pcre2lib from 10.45 to 10.46. (nielsdos) diff --git a/UPGRADING b/UPGRADING index 3bf3e6c09e1a4..13cc9e879aeae 100644 --- a/UPGRADING +++ b/UPGRADING @@ -245,6 +245,7 @@ PHP 8.5 UPGRADE NOTES - EXIF: . Add OffsetTime* Exif tags. + . Added support for HEIF/HEIC. - Intl: . Added class constants NumberFormatter::CURRENCY_ISO, diff --git a/Zend/tests/first_class_callable/constexpr/autoload.phpt b/Zend/tests/first_class_callable/constexpr/autoload.phpt index 2dd2561f9a369..c962b77f12b61 100644 --- a/Zend/tests/first_class_callable/constexpr/autoload.phpt +++ b/Zend/tests/first_class_callable/constexpr/autoload.phpt @@ -26,6 +26,6 @@ var_dump(Closure); Autoloading AutoloadedClass object(Closure)#%d (1) { ["function"]=> - string(16) "withStaticMethod" + string(33) "AutoloadedClass::withStaticMethod" } Called AutoloadedClass::withStaticMethod diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt index efffa4a1d366a..54c96c915635d 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method. +FCC in initializer warns for static reference to trait method. --FILE-- - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt index d36f7c97651e0..97831a8d65f0e 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method (Exception). +FCC in initializer emits deprecation for static reference to trait method (Exception). --FILE-- getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } + } +} + +foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) { + foreach ($reflectionAttribute->newInstance()->value as $fn) { + $r = new \ReflectionFunction($fn); + var_dump($r->getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } +} +echo "=======\n"; +C::foo(); + +?> +--EXPECTF-- +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL +======= +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL diff --git a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt index 3959efbd16a05..1776cd8f319de 100644 --- a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt +++ b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt @@ -23,7 +23,7 @@ var_dump(($c->d)("abc")); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(11) "C::myMethod" + string(11) "P::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/static_call.phpt b/Zend/tests/first_class_callable/constexpr/static_call.phpt index 26761a041a4cc..2c6d3aa92b52f 100644 --- a/Zend/tests/first_class_callable/constexpr/static_call.phpt +++ b/Zend/tests/first_class_callable/constexpr/static_call.phpt @@ -19,7 +19,7 @@ var_dump(Closure); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 2f66d8d5cd2b1..9cb3c7aae4a1f 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1055,6 +1055,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( case ZEND_AST_STATIC_CALL: { zend_function *fptr; + zend_class_entry *called_scope = NULL; switch (ast->kind) { case ZEND_AST_CALL: { ZEND_ASSERT(ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT); @@ -1086,13 +1087,15 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( ZEND_ASSERT(ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT); zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast->child[2]; + zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); + if (!ce) { + return FAILURE; + } + called_scope = ce; + fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr); if (!fptr) { - zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); - if (!ce) { - return FAILURE; - } zend_string *method_name = zend_ast_get_str(ast->child[1]); if (ce->get_static_method) { fptr = ce->get_static_method(ce, method_name); @@ -1145,7 +1148,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } } - zend_create_fake_closure(result, fptr, scope, scope, NULL); + zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL); return SUCCESS; } diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 277204260ce82..c7e12d58c1f53 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -89,6 +89,9 @@ #ifndef __has_feature # define __has_feature(x) 0 #endif +#ifndef __has_include +# define __has_include(x) 0 +#endif #if defined(ZEND_WIN32) && !defined(__clang__) # define ZEND_ASSUME(c) __assume(c) @@ -750,6 +753,10 @@ extern "C++" { # define ZEND_SET_ALIGNED(alignment, decl) decl #endif +#if __has_attribute(section) +# define HAVE_ATTRIBUTE_SECTION +#endif + #define ZEND_SLIDE_TO_ALIGNED(alignment, ptr) (((uintptr_t)(ptr) + ((alignment)-1)) & ~((alignment)-1)) #define ZEND_SLIDE_TO_ALIGNED16(ptr) ZEND_SLIDE_TO_ALIGNED(Z_UL(16), ptr) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 9169861728869..ba7f0304c691f 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -1290,6 +1290,18 @@ typedef struct { mn_offset_mode_t offset_mode; } maker_note_type; +#define FOURCC(id) (((uint32_t)(id[0])<<24) | (id[1]<<16) | (id[2]<<8) | (id[3])) + +typedef struct { + uint64_t size; + uint32_t type; +} isobmff_box_type; + +typedef struct { + uint32_t offset; + uint32_t size; +} isobmff_item_pos_type; + /* Some maker notes (e.g. DJI info tag) require custom parsing */ #define REQUIRES_CUSTOM_PARSING NULL @@ -4279,11 +4291,152 @@ static bool exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offs return result; } +static int exif_isobmff_parse_box(unsigned char *buf, isobmff_box_type *box) +{ + box->size = php_ifd_get32u(buf, 1); + buf += 4; + box->type = php_ifd_get32u(buf, 1); + if (box->size != 1) { + return 8; + } + buf += 4; + box->size = php_ifd_get64u(buf, 1); + return 16; +} + +static void exif_isobmff_parse_meta(unsigned char *data, unsigned char *end, isobmff_item_pos_type *pos) +{ + isobmff_box_type box, item; + unsigned char *box_offset, *p, *p2; + int header_size, exif_id = -1, version, item_count, i; + + for (box_offset = data + 4; box_offset + 16 < end; box_offset += box.size) { + header_size = exif_isobmff_parse_box(box_offset, &box); + if (box.type == FOURCC("iinf")) { + p = box_offset + header_size; + if (p >= end) { + return; + } + version = p[0]; + p += 4; + if (version < 2) { + if (p + 2 >= end) { + return; + } + item_count = php_ifd_get16u(p, 1); + p += 2; + } else { + if (p + 4 >= end) { + return; + } + item_count = php_ifd_get32u(p, 1); + p += 4; + } + for (i = 0; i < item_count && p + 20 < end; i++) { + header_size = exif_isobmff_parse_box(p, &item); + if (p + header_size + 12 >= end) { + return; + } + if (!memcmp(p + header_size + 8, "Exif", 4)) { + exif_id = php_ifd_get16u(p + header_size + 4, 1); + break; + } + p += item.size; + } + if (exif_id < 0) { + break; + } + } + else if (box.type == FOURCC("iloc")) { + p = box_offset + header_size; + if (p >= end) { + return; + } + version = p[0]; + p += 6; + if (version < 2) { + if (p + 2 >= end) { + return; + } + item_count = php_ifd_get16u(p, 1); + p += 2; + } else { + if (p + 4 >= end) { + return; + } + item_count = php_ifd_get32u(p, 1); + p += 4; + } + for (i = 0, p2 = p; i < item_count && p + 16 < end; i++, p2 += 16) { + if (php_ifd_get16u(p2, 1) == exif_id) { + pos->offset = php_ifd_get32u(p2 + 8, 1); + pos->size = php_ifd_get32u(p2 + 12, 1); + break; + } + } + break; + } + } +} + +static bool exif_scan_HEIF_header(image_info_type *ImageInfo, unsigned char *buf) +{ + isobmff_box_type box; + isobmff_item_pos_type pos; + unsigned char *data; + off_t offset; + uint64_t limit; + int box_header_size, remain; + bool ret = false; + + pos.size = 0; + for (offset = php_ifd_get32u(buf, 1); ImageInfo->FileSize > offset + 16; offset += box.size) { + if ((php_stream_seek(ImageInfo->infile, offset, SEEK_SET) < 0) || + (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)buf, 16) != 16)) { + break; + } + box_header_size = exif_isobmff_parse_box(buf, &box); + if (box.type == FOURCC("meta")) { + limit = box.size - box_header_size; + if (limit < 36) { + break; + } + data = (unsigned char *)emalloc(limit); + remain = 16 - box_header_size; + if (remain) { + memcpy(data, buf + box_header_size, remain); + } + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(data + remain), limit - remain) == limit - remain) { + exif_isobmff_parse_meta(data, data + limit, &pos); + } + if ((pos.size) && + (ImageInfo->FileSize >= pos.offset + pos.size) && + (php_stream_seek(ImageInfo->infile, pos.offset + 2, SEEK_SET) >= 0)) { + if (limit >= pos.size - 2) { + limit = pos.size - 2; + } else { + limit = pos.size - 2; + efree(data); + data = (unsigned char *)emalloc(limit); + } + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)data, limit) == limit) { + exif_process_APP1(ImageInfo, (char*)data, limit, pos.offset + 2); + ret = true; + } + } + efree(data); + break; + } + } + + return ret; +} + /* {{{ exif_scan_FILE_header * Parse the marker stream until SOS or EOI is seen; */ static bool exif_scan_FILE_header(image_info_type *ImageInfo) { - unsigned char file_header[8]; + unsigned char file_header[16]; ImageInfo->FileType = IMAGE_FILETYPE_UNKNOWN; @@ -4344,6 +4497,17 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); return false; } + } else if ((ImageInfo->FileSize > 12) && + (!memcmp(file_header + 4, "ftyp", 4)) && + (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(file_header + 8), 4) == 4) && + ((!memcmp(file_header + 8, "heic", 4)) || (!memcmp(file_header + 8, "heix", 4)) || (!memcmp(file_header + 8, "mif1", 4)))) { + if (exif_scan_HEIF_header(ImageInfo, file_header)) { + ImageInfo->FileType = IMAGE_FILETYPE_HEIF; + return true; + } else { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid HEIF file"); + return false; + } } else { exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File not supported"); return false; diff --git a/ext/exif/tests/exif029.phpt b/ext/exif/tests/exif029.phpt new file mode 100644 index 0000000000000..f2eadbfe5d2aa --- /dev/null +++ b/ext/exif/tests/exif029.phpt @@ -0,0 +1,145 @@ +--TEST-- +Check for exif_read_data, HEIF with IFD0 and EXIF data in Motorola byte-order. +--EXTENSIONS-- +exif +--INI-- +output_handler= +zlib.output_compression=0 +--FILE-- + +--EXPECTF-- +array(53) { + ["FileName"]=> + string(13) "image029.heic" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(42199) + ["FileType"]=> + int(20) + ["MimeType"]=> + string(10) "image/heif" + ["SectionsFound"]=> + string(19) "ANY_TAG, IFD0, EXIF" + ["COMPUTED"]=> + array(3) { + ["IsColor"]=> + int(0) + ["ByteOrderMotorola"]=> + int(1) + ["ApertureFNumber"]=> + string(5) "f/1.8" + } + ["Make"]=> + string(5) "Apple" + ["Model"]=> + string(26) "iPhone SE (3rd generation)" + ["Orientation"]=> + int(1) + ["XResolution"]=> + string(4) "72/1" + ["YResolution"]=> + string(4) "72/1" + ["ResolutionUnit"]=> + int(2) + ["Software"]=> + string(6) "17.2.1" + ["DateTime"]=> + string(19) "2024:02:21 16:03:50" + ["HostComputer"]=> + string(26) "iPhone SE (3rd generation)" + ["TileWidth"]=> + int(512) + ["TileLength"]=> + int(512) + ["Exif_IFD_Pointer"]=> + int(264) + ["ExposureTime"]=> + string(4) "1/60" + ["FNumber"]=> + string(3) "9/5" + ["ExposureProgram"]=> + int(2) + ["ISOSpeedRatings"]=> + int(200) + ["ExifVersion"]=> + string(4) "0232" + ["DateTimeOriginal"]=> + string(19) "2024:02:21 16:03:50" + ["DateTimeDigitized"]=> + string(19) "2024:02:21 16:03:50" + ["OffsetTime"]=> + string(6) "+08:00" + ["OffsetTimeOriginal"]=> + string(6) "+08:00" + ["OffsetTimeDigitized"]=> + string(6) "+08:00" + ["ShutterSpeedValue"]=> + string(12) "159921/27040" + ["ApertureValue"]=> + string(11) "54823/32325" + ["BrightnessValue"]=> + string(11) "29968/13467" + ["ExposureBiasValue"]=> + string(3) "0/1" + ["MeteringMode"]=> + int(5) + ["Flash"]=> + int(16) + ["FocalLength"]=> + string(7) "399/100" + ["SubjectLocation"]=> + array(4) { + [0]=> + int(1995) + [1]=> + int(1507) + [2]=> + int(2217) + [3]=> + int(1332) + } + ["MakerNote"]=> + string(9) "Apple iOS" + ["SubSecTimeOriginal"]=> + string(3) "598" + ["SubSecTimeDigitized"]=> + string(3) "598" + ["ColorSpace"]=> + int(65535) + ["ExifImageWidth"]=> + int(4032) + ["ExifImageLength"]=> + int(3024) + ["SensingMethod"]=> + int(2) + ["SceneType"]=> + string(1) "" + ["ExposureMode"]=> + int(0) + ["WhiteBalance"]=> + int(0) + ["DigitalZoomRatio"]=> + string(7) "756/151" + ["FocalLengthIn35mmFilm"]=> + int(140) + ["UndefinedTag:0xA432"]=> + array(4) { + [0]=> + string(15) "4183519/1048501" + [1]=> + string(15) "4183519/1048501" + [2]=> + string(3) "9/5" + [3]=> + string(3) "9/5" + } + ["UndefinedTag:0xA433"]=> + string(5) "Apple" + ["UndefinedTag:0xA434"]=> + string(51) "iPhone SE (3rd generation) back camera 3.99mm f/1.8" + ["UndefinedTag:0xA460"]=> + int(2) +} diff --git a/ext/exif/tests/image029.heic b/ext/exif/tests/image029.heic new file mode 100644 index 0000000000000..99f8186d0723b Binary files /dev/null and b/ext/exif/tests/image029.heic differ diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index f597df36e290c..f0d3379534591 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2974,10 +2974,22 @@ static void accel_globals_dtor(zend_accel_globals *accel_globals) # include # define MAP_HUGETLB MAP_ALIGNED_SUPER # endif +# if __has_include() +# include +# endif +# if __has_include() +# include +# endif # endif -# if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) -static zend_result accel_remap_huge_pages(void *start, size_t size, size_t real_size, const char *name, size_t offset) +# define ZEND_HUGE_PAGE_SIZE (2UL * 1024 * 1024) + +# if (defined(__linux__) || defined(__FreeBSD__)) && (defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE)) && defined(HAVE_ATTRIBUTE_ALIGNED) && defined(HAVE_ATTRIBUTE_SECTION) && __has_include() && __has_include() +static zend_result +__attribute__((section(".remap_stub"))) +__attribute__((aligned(ZEND_HUGE_PAGE_SIZE))) +zend_never_inline +accel_remap_huge_pages(void *start, size_t size, size_t real_size) { void *ret = MAP_FAILED; void *mem; @@ -3030,94 +3042,113 @@ static zend_result accel_remap_huge_pages(void *start, size_t size, size_t real_ // Given the MAP_FIXED flag the address can never diverge ZEND_ASSERT(ret == start); - zend_mmap_set_name(start, size, "zend_huge_code_pages"); + memcpy(start, mem, real_size); mprotect(start, size, PROT_READ | PROT_EXEC); + zend_mmap_set_name(start, size, "zend_huge_code_pages"); munmap(mem, size); return SUCCESS; } -static void accel_move_code_to_huge_pages(void) -{ +static int accel_dl_iterate_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) { + if (info->dlpi_name == NULL || strcmp(info->dlpi_name, "") == 0) { + *((uintptr_t*)data) = info->dlpi_addr; + return 1; + } + return 0; +} + +static zend_result accel_find_program_section(ElfW(Shdr) *section) { + + uintptr_t base_addr; + if (dl_iterate_phdr(accel_dl_iterate_phdr_callback, &base_addr) != 1) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: executable base address not found"); + return FAILURE; + } + #if defined(__linux__) - FILE *f; - long unsigned int huge_page_size = 2 * 1024 * 1024; - - f = fopen("/proc/self/maps", "r"); - if (f) { - long unsigned int start, end, offset, inode; - char perm[5], dev[10], name[MAXPATHLEN]; - int ret; - extern char *__progname; - char buffer[MAXPATHLEN]; - - while (fgets(buffer, MAXPATHLEN, f)) { - ret = sscanf(buffer, "%lx-%lx %4s %lx %9s %lu %s\n", &start, &end, perm, &offset, dev, &inode, name); - if (ret >= 6) { - /* try to find the php text segment and map it into huge pages - Lines without 'name' are going to be skipped */ - if (ret > 6 && perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/' \ - && strstr(name, __progname)) { - long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); - long unsigned int seg_end = (end & ~(huge_page_size-1L)); - long unsigned int real_end; - - ret = fscanf(f, "%lx-", &start); - if (ret == 1 && start == seg_end + huge_page_size) { - real_end = end; - seg_end = start; - } else { - real_end = seg_end; - } + FILE *f = fopen("/proc/self/exe", "r"); +#elif defined(__FreeBSD__) + char path[4096]; + int mib[4]; + size_t len = sizeof(path); - if (seg_end > seg_start) { - zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, name); - accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, real_end - seg_start, name, offset + seg_start - start); - } - break; - } - } - } + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; /* Current process */ + + if (sysctl(mib, 4, path, &len, NULL, 0) == -1) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: sysctl(KERN_PROC_PATHNAME) failed: %s (%d)", + strerror(errno), errno); + return FAILURE; + } + + FILE *f = fopen(path, "r"); +#endif + if (!f) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fopen(/proc/self/exe) failed: %s (%d)", + strerror(errno), errno); + return FAILURE; + } + + /* Read ELF header */ + ElfW(Ehdr) ehdr; + if (!fread(&ehdr, sizeof(ehdr), 1, f)) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fread() failed: %s (%d)", + strerror(errno), errno); fclose(f); + return FAILURE; } -#elif defined(__FreeBSD__) - size_t s = 0; - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; - long unsigned int huge_page_size = 2 * 1024 * 1024; - if (sysctl(mib, 4, NULL, &s, NULL, 0) == 0) { - s = s * 4 / 3; - void *addr = mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); - if (addr != MAP_FAILED) { - if (sysctl(mib, 4, addr, &s, NULL, 0) == 0) { - uintptr_t start = (uintptr_t)addr; - uintptr_t end = start + s; - while (start < end) { - struct kinfo_vmentry *entry = (struct kinfo_vmentry *)start; - size_t sz = entry->kve_structsize; - if (sz == 0) { - break; - } - int permflags = entry->kve_protection; - if ((permflags & KVME_PROT_READ) && !(permflags & KVME_PROT_WRITE) && - (permflags & KVME_PROT_EXEC) && entry->kve_path[0] != '\0') { - long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); - long unsigned int seg_end = (end & ~(huge_page_size-1L)); - if (seg_end > seg_start) { - zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, entry->kve_path); - accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, seg_end - seg_start, entry->kve_path, entry->kve_offset + seg_start - start); - // First relevant segment found is our binary - break; - } - } - start += sz; - } - } - munmap(addr, s); + + /* Read section headers */ + ElfW(Shdr) shdrs[ehdr.e_shnum]; + if (fseek(f, ehdr.e_shoff, SEEK_SET) != 0) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fseek() failed: %s (%d)", + strerror(errno), errno); + fclose(f); + return FAILURE; + } + if (fread(shdrs, sizeof(shdrs[0]), ehdr.e_shnum, f) != ehdr.e_shnum) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fread() failed: %s (%d)", + strerror(errno), errno); + fclose(f); + return FAILURE; + } + + fclose(f); + + /* Find the program section */ + for (ElfW(Half) idx = 0; idx < ehdr.e_shnum; idx++) { + ElfW(Shdr) *sh = &shdrs[idx]; + uintptr_t start = (uintptr_t)sh->sh_addr + base_addr; + zend_accel_error(ACCEL_LOG_DEBUG, "considering section %016" PRIxPTR "-%016" PRIxPTR " vs %016" PRIxPTR "\n", start, start + sh->sh_size, (uintptr_t)accel_find_program_section); + if ((uintptr_t)accel_find_program_section >= start && (uintptr_t)accel_find_program_section < start + sh->sh_size) { + *section = *sh; + section->sh_addr = (ElfW(Addr))start; + return SUCCESS; } } -#endif + + return FAILURE; +} + +static void accel_move_code_to_huge_pages(void) +{ + ElfW(Shdr) section; + if (accel_find_program_section(§ion) == FAILURE) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: program section not found"); + return; + } + + uintptr_t start = ZEND_MM_ALIGNED_SIZE_EX(section.sh_addr, ZEND_HUGE_PAGE_SIZE); + uintptr_t end = (section.sh_addr + section.sh_size) & ~(ZEND_HUGE_PAGE_SIZE-1UL); + if (end > start) { + zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %" PRIxPTR "-%" PRIxPTR "\n", start, end); + accel_remap_huge_pages((void*)start, end - start, end - start); + } } # else static void accel_move_code_to_huge_pages(void) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index fcfe1bffa744a..57f7e189e6c41 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -2734,7 +2734,15 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) /* Stack must be 16 byte aligned */ /* TODO: select stack size ??? */ #if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# if defined(IR_TARGET_AARCH64) + /* Must save LR */ + jit->ctx.flags |= IR_USE_FRAME_POINTER; + /* Same as HYBRID VM */ + jit->ctx.fixed_stack_frame_size = sizeof(void*) * 4; /* 4 spill slots */ +# else + /* Same as HYBRID VM, plus 1 slot for re-alignment (caller pushes return address, frame is not aligned on entry) */ jit->ctx.fixed_stack_frame_size = sizeof(void*) * 5; /* 5 spill slots (8 bytes) or 10 spill slots (4 bytes) */ +# endif #elif defined(IR_TARGET_AARCH64) jit->ctx.flags |= IR_USE_FRAME_POINTER; jit->ctx.fixed_stack_frame_size = sizeof(void*) * 16; /* 10 saved registers and 6 spill slots (8 bytes) */ diff --git a/ext/standard/tests/image/image_type_to_mime_type_basic.phpt b/ext/standard/tests/image/image_type_to_mime_type_basic.phpt index 6fb5154007642..a393c3e83dc27 100644 --- a/ext/standard/tests/image/image_type_to_mime_type_basic.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type_basic.phpt @@ -21,6 +21,7 @@ $image_types = array ( IMAGETYPE_IFF, IMAGETYPE_WBMP, IMAGETYPE_JPEG2000, + IMAGETYPE_HEIF, IMAGETYPE_XBM, IMAGETYPE_WEBP, IMAGETYPE_HEIF, @@ -50,6 +51,7 @@ string(24) "application/octet-stream" string(9) "image/iff" string(18) "image/vnd.wap.wbmp" string(24) "application/octet-stream" +string(10) "image/heif" string(9) "image/xbm" string(10) "image/webp" string(10) "image/heif"