From 7e282b3cc8e42e13a53a69a3965152f922e26257 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 22 Nov 2025 10:02:19 +0200 Subject: [PATCH 1/5] Start adding CI --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0a21afe --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + name: "Build and test" + runs-on: ubuntu-latest + continue-on-error: false + strategy: + fail-fast: false + matrix: + php: ['8.3', '8.4', '8.5'] + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: phpize + + - name: Set up + run: phpize + + - name: Configure + run: ./configure --enable-custom_cast + + - name: Make and install + run: make -j"$(nproc)" install + + - name: Run tests + run: >- + REPORT_EXIT_STATUS=1 + NO_INTERACTION=1 + TEST_PHP_EXECUTABLE=$(which php) + php run-tests.php -n --show-diff tests From db55d8fceec4efb210fde6d61d463faf57edecc0 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 22 Nov 2025 10:03:29 +0200 Subject: [PATCH 2/5] sudo --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a21afe..ddf2c8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: run: ./configure --enable-custom_cast - name: Make and install - run: make -j"$(nproc)" install + run: sudo make -j"$(nproc)" install - name: Run tests run: >- From 9c0b48e79461e14edaa05ea698ee6c64a9c90311 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 22 Nov 2025 10:12:15 +0200 Subject: [PATCH 3/5] start delayed target validation --- custom_cast.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/custom_cast.c b/custom_cast.c index d0c2a30..f5912c3 100644 --- a/custom_cast.c +++ b/custom_cast.c @@ -267,25 +267,22 @@ static zend_result custom_cast_do_cast( /** * Ensure that the flags for a class entry correspond to a userland class */ -static void require_user_class(uint32_t flags) { +static const char* require_user_class(uint32_t flags) { // Must actually be on a class if (flags & ZEND_ACC_ENUM) { - zend_error_noreturn(E_ERROR, "Cannot apply #[CustomCasting\\CustomCastable] to enum"); + return "Cannot apply #[CustomCasting\\CustomCastable] to enum"; } if (flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot apply #[CustomCasting\\CustomCastable] to interface"); + return "Cannot apply #[CustomCasting\\CustomCastable] to interface"; } if (flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot apply #[CustomCasting\\CustomCastable] to trait"); + return "Cannot apply #[CustomCasting\\CustomCastable] to trait"; } // Use ce->type != ZEND_INTERNAL_CLASS if (flags & ZEND_ACC_LINKED) { - zend_error_noreturn( - E_ERROR, - "#[CustomCasting\\CustomCastable] is for user classes, internal classes can set a custom cast handler" - ); + return "#[CustomCasting\\CustomCastable] is for user classes, internal classes can set a custom cast handler"; } - + return NULL; } /** @@ -381,7 +378,10 @@ static void ensure_class_has_interface(zend_class_entry *scope) { static void validate_custom_castable( zend_attribute *attr, uint32_t target, zend_class_entry *scope) { - require_user_class(scope->ce_flags); + const char *error = require_user_class(scope->ce_flags); + if (error != NULL) { + zend_error_noreturn(E_ERROR, error); + } ensure_class_has_interface(scope); scope->default_object_handlers = &custom_cast_obj_handlers; } From 86803e52277784da93d57f1c2b1abfb6d2d3c6da Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 22 Nov 2025 10:19:42 +0200 Subject: [PATCH 4/5] 8.5 take 1 --- custom_cast.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/custom_cast.c b/custom_cast.c index f5912c3..f59e056 100644 --- a/custom_cast.c +++ b/custom_cast.c @@ -375,15 +375,27 @@ static void ensure_class_has_interface(zend_class_entry *scope) { scope->interface_names = newInterfaceSet; } +#if PHP_VERSION_ID < 80500 static void validate_custom_castable( zend_attribute *attr, uint32_t target, zend_class_entry *scope) +#else +static zend_string *validate_custom_castable( + zend_attribute *attr, uint32_t target, zend_class_entry *scope) +#endif { const char *error = require_user_class(scope->ce_flags); if (error != NULL) { +#if PHP_VERSION_ID < 80500 zend_error_noreturn(E_ERROR, error); +#else + return zend_string_init(error, strlen(error), 0); +#endif } ensure_class_has_interface(scope); scope->default_object_handlers = &custom_cast_obj_handlers; +#if PHP_VERSION_ID >= 80500 + return NULL; +#endif } static void setup_CustomCastable_as_attribute(zend_class_entry *class_entry) { From e01b1280fda88a94682b0fd8ca86cade2a7fd70f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 22 Nov 2025 10:24:14 +0200 Subject: [PATCH 5/5] compatibility with php #15993 --- tests/attribute_on_wrong/attribute_on_class_missing.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/attribute_on_wrong/attribute_on_class_missing.phpt b/tests/attribute_on_wrong/attribute_on_class_missing.phpt index 6c8577c..6849b21 100644 --- a/tests/attribute_on_wrong/attribute_on_class_missing.phpt +++ b/tests/attribute_on_wrong/attribute_on_class_missing.phpt @@ -13,4 +13,4 @@ class Demo { ?> --EXPECTF-- -Fatal error: Class Demo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (CustomCasting\HasCustomCast::__doCast) in %s on line %d \ No newline at end of file +Fatal error: Class Demo contains 1 abstract method and must therefore be declared abstract or implement the remaining method%rs?%r (CustomCasting\HasCustomCast::__doCast) in %s on line %d \ No newline at end of file