diff --git a/.github/actions/zts/Dockerfile b/.github/actions/zts/Dockerfile index 1a87d082a6..b0e60d3e58 100644 --- a/.github/actions/zts/Dockerfile +++ b/.github/actions/zts/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1-zts +FROM php:8.2-zts WORKDIR /tmp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73feb9b9c9..6176b86683 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - php: ["8.0", "8.1"] + php: ["8.0", "8.1", "8.2"] rust: [stable, nightly] clang: ["14"] phpts: [ts, nts] @@ -39,6 +39,7 @@ jobs: php-version: ${{ matrix.php }} env: phpts: ${{ matrix.phpts }} + debug: true - name: Setup Rust uses: dtolnay/rust-toolchain@master with: @@ -87,17 +88,17 @@ jobs: - name: Test inline examples run: cargo test --release --all --all-features - name: Run rustfmt - if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1' + if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2' run: cargo fmt --all -- --check - name: Run clippy - if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1' + if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2' run: cargo clippy --all -- -D warnings # Docs - name: Run rustdoc - if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1' + if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2' run: cargo rustdoc -- -D warnings - name: Build with docs stub - if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1' + if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2' env: DOCS_RS: "" run: cargo clean && cargo build diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0719b641a8..5f55df1c91 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest"] - php: ["8.0"] + php: ["8.2"] clang: ["14"] mdbook: ["latest"] steps: diff --git a/build.rs b/build.rs index c2c5b9e564..fb06b28ec7 100644 --- a/build.rs +++ b/build.rs @@ -16,7 +16,7 @@ use bindgen::RustTarget; use impl_::Provider; const MIN_PHP_API_VER: u32 = 20200930; -const MAX_PHP_API_VER: u32 = 20210902; +const MAX_PHP_API_VER: u32 = 20220829; pub trait PHPProvider<'a>: Sized { /// Create a new PHP provider. @@ -208,10 +208,18 @@ fn check_php_version(info: &PHPInfo) -> Result<()> { // should get both the `php81` and `php82` flags. const PHP_81_API_VER: u32 = 20210902; - if version >= PHP_81_API_VER { + const PHP_82_API_VER: u32 = 20220829; + + println!("cargo:rustc-cfg=php80"); + + if (PHP_81_API_VER..PHP_82_API_VER).contains(&version) { println!("cargo:rustc-cfg=php81"); } + if version >= PHP_82_API_VER { + println!("cargo:rustc-cfg=php82"); + } + Ok(()) } @@ -233,12 +241,13 @@ fn main() -> Result<()> { } println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=Cargo.lock"); // docs.rs runners only have PHP 7.4 - use pre-generated bindings if env::var("DOCS_RS").is_ok() { println!("cargo:warning=docs.rs detected - using stub bindings"); println!("cargo:rustc-cfg=php_debug"); - println!("cargo:rustc-cfg=php81"); + println!("cargo:rustc-cfg=php82"); std::fs::copy("docsrs_bindings.rs", out_path) .expect("failed to copy docs.rs stub bindings to out directory"); return Ok(()); diff --git a/docsrs_bindings.rs b/docsrs_bindings.rs index ff121e3fc7..a2ecbc71fc 100644 --- a/docsrs_bindings.rs +++ b/docsrs_bindings.rs @@ -54,7 +54,6 @@ pub const ZEND_ACC_USE_GUARDS: u32 = 2048; pub const ZEND_ACC_CONSTANTS_UPDATED: u32 = 4096; pub const ZEND_ACC_NO_DYNAMIC_PROPERTIES: u32 = 8192; pub const ZEND_HAS_STATIC_IN_METHODS: u32 = 16384; -pub const ZEND_ACC_REUSE_GET_ITERATOR: u32 = 65536; pub const ZEND_ACC_RESOLVED_PARENT: u32 = 131072; pub const ZEND_ACC_RESOLVED_INTERFACES: u32 = 262144; pub const ZEND_ACC_UNRESOLVED_VARIANCE: u32 = 524288; @@ -80,7 +79,7 @@ pub const ZEND_ACC_STRICT_TYPES: u32 = 2147483648; pub const ZEND_ISEMPTY: u32 = 1; pub const _ZEND_SEND_MODE_SHIFT: u32 = 25; pub const _ZEND_IS_VARIADIC_BIT: u32 = 134217728; -pub const ZEND_MODULE_API_NO: u32 = 20210902; +pub const ZEND_MODULE_API_NO: u32 = 20220829; pub const USING_ZTS: u32 = 0; pub const MAY_BE_BOOL: u32 = 12; pub const MAY_BE_ANY: u32 = 1022; @@ -219,7 +218,7 @@ pub struct _zend_array { pub gc: zend_refcounted_h, pub u: _zend_array__bindgen_ty_1, pub nTableMask: u32, - pub arData: *mut Bucket, + pub __bindgen_anon_1: _zend_array__bindgen_ty_2, pub nNumUsed: u32, pub nNumOfElements: u32, pub nTableSize: u32, @@ -241,6 +240,13 @@ pub struct _zend_array__bindgen_ty_1__bindgen_ty_1 { pub nIteratorsCount: zend_uchar, pub _unused2: zend_uchar, } +#[repr(C)] +#[derive(Copy, Clone)] +pub union _zend_array__bindgen_ty_2 { + pub arHash: *mut u32, + pub arData: *mut Bucket, + pub arPacked: *mut zval, +} pub type HashPosition = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -420,6 +426,15 @@ pub struct _zend_class_iterator_funcs { pub type zend_class_iterator_funcs = _zend_class_iterator_funcs; #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct _zend_class_arrayaccess_funcs { + pub zf_offsetget: *mut zend_function, + pub zf_offsetexists: *mut zend_function, + pub zf_offsetset: *mut zend_function, + pub zf_offsetunset: *mut zend_function, +} +pub type zend_class_arrayaccess_funcs = _zend_class_arrayaccess_funcs; +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct _zend_serialize_data { _unused: [u8; 0], } @@ -468,6 +483,7 @@ pub struct _zend_class_mutable_data { pub default_properties_table: *mut zval, pub constants_table: *mut HashTable, pub ce_flags: u32, + pub backed_enum_table: *mut HashTable, } pub type zend_class_mutable_data = _zend_class_mutable_data; #[repr(C)] @@ -510,11 +526,11 @@ pub struct _zend_class_entry { pub default_static_members_count: ::std::os::raw::c_int, pub default_properties_table: *mut zval, pub default_static_members_table: *mut zval, - pub static_members_table__ptr: *mut *mut zval, + pub static_members_table__ptr: *mut zval, pub function_table: HashTable, pub properties_info: HashTable, pub constants_table: HashTable, - pub mutable_data__ptr: *mut *mut zend_class_mutable_data, + pub mutable_data__ptr: *mut zend_class_mutable_data, pub inheritance_cache: *mut zend_inheritance_cache_entry, pub properties_info_table: *mut *mut _zend_property_info, pub constructor: *mut zend_function, @@ -531,6 +547,7 @@ pub struct _zend_class_entry { pub __serialize: *mut zend_function, pub __unserialize: *mut zend_function, pub iterator_funcs_ptr: *mut zend_class_iterator_funcs, + pub arrayaccess_funcs_ptr: *mut zend_class_arrayaccess_funcs, pub __bindgen_anon_2: _zend_class_entry__bindgen_ty_2, pub get_iterator: ::std::option::Option< unsafe extern "C" fn( @@ -728,10 +745,10 @@ pub type zend_object_cast_t = ::std::option::Option< readobj: *mut zend_object, retval: *mut zval, type_: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int, + ) -> zend_result, >; pub type zend_object_count_elements_t = ::std::option::Option< - unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> ::std::os::raw::c_int, + unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> zend_result, >; pub type zend_object_get_closure_t = ::std::option::Option< unsafe extern "C" fn( @@ -740,7 +757,7 @@ pub type zend_object_get_closure_t = ::std::option::Option< fptr_ptr: *mut *mut zend_function, obj_ptr: *mut *mut zend_object, check_only: bool, - ) -> ::std::os::raw::c_int, + ) -> zend_result, >; pub type zend_object_get_gc_t = ::std::option::Option< unsafe extern "C" fn( @@ -755,7 +772,7 @@ pub type zend_object_do_operation_t = ::std::option::Option< result: *mut zval, op1: *mut zval, op2: *mut zval, - ) -> ::std::os::raw::c_int, + ) -> zend_result, >; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -903,13 +920,13 @@ pub struct _zend_op_array { pub required_num_args: u32, pub arg_info: *mut zend_arg_info, pub attributes: *mut HashTable, + pub T: u32, + pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, pub cache_size: ::std::os::raw::c_int, pub last_var: ::std::os::raw::c_int, - pub T: u32, pub last: u32, pub opcodes: *mut zend_op, - pub run_time_cache__ptr: *mut *mut *mut ::std::os::raw::c_void, - pub static_variables_ptr__ptr: *mut *mut HashTable, + pub static_variables_ptr__ptr: *mut HashTable, pub static_variables: *mut HashTable, pub vars: *mut *mut zend_string, pub refcount: *mut u32, @@ -943,6 +960,8 @@ pub struct _zend_internal_function { pub required_num_args: u32, pub arg_info: *mut zend_internal_arg_info, pub attributes: *mut HashTable, + pub T: u32, + pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, pub handler: zif_handler, pub module: *mut _zend_module_entry, pub reserved: [*mut ::std::os::raw::c_void; 6usize], @@ -970,6 +989,8 @@ pub struct _zend_function__bindgen_ty_1 { pub required_num_args: u32, pub arg_info: *mut zend_arg_info, pub attributes: *mut HashTable, + pub T: u32, + pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void, } #[repr(C)] pub struct _zend_execute_data { @@ -998,6 +1019,12 @@ extern "C" { } #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct zend_atomic_bool_s { + pub value: u8, +} +pub type zend_atomic_bool = zend_atomic_bool_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct _zend_stack { pub size: ::std::os::raw::c_int, pub top: ::std::os::raw::c_int, @@ -1073,8 +1100,8 @@ pub struct _zend_executor_globals { pub in_autoload: *mut HashTable, pub full_tables_cleanup: bool, pub no_extensions: bool, - pub vm_interrupt: bool, - pub timed_out: bool, + pub vm_interrupt: zend_atomic_bool, + pub timed_out: zend_atomic_bool, pub hard_timeout: zend_long, pub regular_list: HashTable, pub persistent_list: HashTable, @@ -1118,6 +1145,8 @@ pub struct _zend_executor_globals { pub record_errors: bool, pub num_errors: u32, pub errors: *mut *mut zend_error_info, + pub filename_override: *mut zend_string, + pub lineno_override: zend_long, pub reserved: [*mut ::std::os::raw::c_void; 6usize], } pub type zend_module_entry = _zend_module_entry; diff --git a/src/builders/class.rs b/src/builders/class.rs index 76094455e5..91a6a010fc 100644 --- a/src/builders/class.rs +++ b/src/builders/class.rs @@ -247,7 +247,7 @@ impl ClassBuilder { // disable serialization if the class has an associated object if self.object_override.is_some() { cfg_if::cfg_if! { - if #[cfg(php81)] { + if #[cfg(any(php81, php82))] { class.ce_flags |= ClassFlags::NotSerializable.bits(); } else { class.serialize = Some(crate::ffi::zend_class_serialize_deny); diff --git a/src/flags.rs b/src/flags.rs index debd960d02..f219210ad6 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -2,6 +2,8 @@ use bitflags::bitflags; +#[cfg(not(php82))] +use crate::ffi::ZEND_ACC_REUSE_GET_ITERATOR; use crate::ffi::{ CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, IS_ARRAY, IS_CALLABLE, IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR, @@ -14,10 +16,10 @@ use crate::ffi::{ ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED, ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE, ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES, - ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_REUSE_GET_ITERATOR, - ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES, ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, - ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE, ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, - ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS, Z_TYPE_FLAGS_SHIFT, _IS_BOOL, + ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES, + ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE, + ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS, + Z_TYPE_FLAGS_SHIFT, _IS_BOOL, }; use std::{convert::TryFrom, fmt::Display}; @@ -75,13 +77,14 @@ bitflags! { const ConstantsUpdated = ZEND_ACC_CONSTANTS_UPDATED; const NoDynamicProperties = ZEND_ACC_NO_DYNAMIC_PROPERTIES; const HasStaticInMethods = ZEND_HAS_STATIC_IN_METHODS; + #[cfg(not(php82))] const ReuseGetIterator = ZEND_ACC_REUSE_GET_ITERATOR; const ResolvedParent = ZEND_ACC_RESOLVED_PARENT; const ResolvedInterfaces = ZEND_ACC_RESOLVED_INTERFACES; const UnresolvedVariance = ZEND_ACC_UNRESOLVED_VARIANCE; const NearlyLinked = ZEND_ACC_NEARLY_LINKED; - #[cfg(php81)] + #[cfg(any(php81,php82))] const NotSerializable = crate::ffi::ZEND_ACC_NOT_SERIALIZABLE; } } diff --git a/src/types/array.rs b/src/types/array.rs index cfd99cda2f..11084930d0 100644 --- a/src/types/array.rs +++ b/src/types/array.rs @@ -531,11 +531,18 @@ impl<'a> Iter<'a> { /// /// * `ht` - The hashtable to iterate. pub fn new(ht: &'a ZendHashTable) -> Self { - Self { + #[cfg(not(php82))] + return Self { ht, pos: NonNull::new(ht.arData), end: NonNull::new(unsafe { ht.arData.offset(ht.nNumUsed as isize) }), - } + }; + #[cfg(php82)] + return Self { + ht, + pos: NonNull::new(unsafe { ht.__bindgen_anon_1.arData }), + end: NonNull::new(unsafe { ht.__bindgen_anon_1.arData.offset(ht.nNumUsed as isize) }), + }; } } diff --git a/src/types/string.rs b/src/types/string.rs index 6256ee23a3..94cc1f5efb 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -251,7 +251,7 @@ impl ZendStr { /// assert_eq!(s.len(), 13); /// ``` pub fn len(&self) -> usize { - self.len as usize + self.len } /// Returns true if the string is empty, false otherwise. diff --git a/src/zend/ex.rs b/src/zend/ex.rs index f14e62c7ee..dada00e0c8 100644 --- a/src/zend/ex.rs +++ b/src/zend/ex.rs @@ -213,7 +213,7 @@ impl ExecuteData { #[doc(hidden)] unsafe fn zend_call_var_num(&self, n: isize) -> *mut Zval { let ptr = self as *const Self as *mut Zval; - ptr.offset(Self::zend_call_frame_slot() + n as isize) + ptr.offset(Self::zend_call_frame_slot() + n) } /// Translation of macro `ZEND_CALL_FRAME_SLOT`