Skip to content

Reapply GH-17712 with a fix for internal class constants #18464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: PHP-8.4
Choose a base branch
from

Conversation

DanielEScherzer
Copy link
Member

@DanielEScherzer DanielEScherzer commented Apr 29, 2025

Add recursion protection when emitting deprecation warnings for class constants, since the deprecation message can come from an attribute that is using the same constant for the message, or otherwise result in recursion.

But, internal constants are persisted, and thus cannot have recursion protection. Otherwise, if a user error handler triggers bailout before the recursion flag is removed then a subsequent request (e.g. with --repeat 2) would start with that flag already applied. Internal constants can presumably be trusted not to use deprecation messages that come from recursive attributes.

Fixes GH-18463
Fixes GH-17711

@DanielEScherzer DanielEScherzer changed the base branch from master to PHP-8.4 April 29, 2025 22:51
@DanielEScherzer
Copy link
Member Author

@php/release-managers-84 this fixes a regression from #17712 that is part of the not-yet-released PHP 8.4.7. Should this be included in 8.4.7 rather than waiting for 8.4.8?

Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should work. Thank you!

@DanielEScherzer
Copy link
Member Author

<adding the PHP 8.4 release managers as reviewers - if this should be included in 8.4.7 I'd rather one of you merge this, if it should wait until 8.4.8 let me know and I can merge it>

@DanielEScherzer
Copy link
Member Author

DanielEScherzer commented Apr 29, 2025

So it seems that something is setting ZEND_ACC_DEPRECATED in the flags for the constant (u2.constant_flags) rather than using CONST_DEPRECATED and the module number; ZEND_ACC_DEPRECATED is 1 << 11, so the module number is treated as 1 << 3 and thus not PHP_USER_CONSTANT
But that is because ZEND_CLASS_CONST_FLAGS() is using it to hold a bunch of flags, like private, final, etc., that aren't applicable to normal constants

Copy link
Member

@SakiTakamachi SakiTakamachi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have decided to include this in version 8.4.7.

I plan to package RC2 with this change later today (Japan time), and will make an announcement once QA is complete.

If everything goes smoothly, I will release 8.4.7 as scheduled next week.

@DanielEScherzer
Copy link
Member Author

DanielEScherzer commented Apr 30, 2025

Okay, I'm working on a fix now for the class constants

@iluuu1994
Copy link
Member

Obviously, we'll need to check why this segfaults. 🙂

@DanielEScherzer
Copy link
Member Author

Obviously, we'll need to check why this segfaults. 🙂

Segfault is from the module number being 8 because of ZEND_ACC_DEPRECATED

@iluuu1994
Copy link
Member

iluuu1994 commented Apr 30, 2025

Ah sorry, I missed your earlier comment. I don't quite understand your explanation, and why that would cause a segfault now but not before. But it's way too late for me now, so I'll check tomorrow if you haven't already found the solution.

@DanielEScherzer
Copy link
Member Author

Ah sorry, I missed your earlier comment. I don't quite understand your explanation, and why that would cause a segfault now but not before. But it's way too late for me now, so I'll check tomorrow if you haven't already found the solution.

The segfault now is from infinite recursion. Because ZEND_ACC_DEPRECATED is 1<<11, ZEND_CONSTANT_MODULE_NUMBER() returns 3 rather than PHP_USER_CONSTANT (0x7fffff)

@iluuu1994
Copy link
Member

Ah ofc, makes sense.

@DanielEScherzer
Copy link
Member Author

DanielEScherzer commented Apr 30, 2025

Okay, this is a bit trickier that that, because a class constant needs to be able to have the following flags

  1. ZEND_ACC_PUBLIC
  2. ZEND_ACC_PROTECTED
  3. ZEND_ACC_PRIVATE
  4. ZEND_ACC_FINAL
  5. ZEND_CLASS_CONST_IS_CASE
  6. ZEND_ACC_DEPRECATED
    and, for the CONST_ flags, at least some of
  7. CONST_PERSISTENT
  8. CONST_NO_FILE_CACHE
  9. CONST_DEPRECATED
  10. CONST_OWNED
  11. CONST_RECURSIVE
    plus, during evaluation
  12. IS_CONSTANT_VISITED_MARK

So basically class constants can't store the module number in the top 3 bytes if they want to support all of the things, and I'll adjust so that we have 16 bits for the flags (which is what I thought was already the case when I wrote https://php.github.io/php-src/core/data-structures/zend_constant.html). This limits the number of modules possible to 2^16 rather than 2^24, which should still be enough.

I'll clean things up on master to be better documented

@iluuu1994 iluuu1994 self-requested a review April 30, 2025 08:47
@iluuu1994
Copy link
Member

iluuu1994 commented Apr 30, 2025

Do we need to store the module id at all? I see this was not done previously for class constants, so can we not just check for if (c->ce->type == ZEND_USER_CLASS) { instead? This PR is ABI breaking (ZEND_CONSTANT_MODULE_NUMBER() from extensions that aren't recompiled will incorrectly access the module number).

The analogous fix for global constants can use ZEND_CONSTANT_MODULE_NUMBER() instead.

@remicollet
Copy link
Member

Perhaps simpler to revert the problem (for 8.4.7RC2/8.4.7) and give more time for a proper fix in 8.4.8 ?

@iluuu1994
Copy link
Member

I can revert GH-17712 and postpone until 8.4.8 if RMs prefer. Let me know if I should do that. Otherwise, I believe the if (c->ce->type == ZEND_USER_CLASS) { approach should work.

@DanielEScherzer
Copy link
Member Author

Do we need to store the module id at all? I see this was not done previously for class constants, so can we not just check for if (c->ce->type == ZEND_USER_CLASS) { instead? This PR is ABI breaking (ZEND_CONSTANT_MODULE_NUMBER() from extensions that aren't recompiled will incorrectly access the module number).

The analogous fix for global constants can use ZEND_CONSTANT_MODULE_NUMBER() instead.

Where would we check c->ce->type? The recursion protection is also used by global constants where c->ce isn't present

@iluuu1994
Copy link
Member

@DanielEScherzer Sadly, you can't add them to the macros but you'll have to add it around them at call-site. Regardless, I think it's better to revert GH-17712 for now so that we can tag. I'll do that in approx. half an hour. We can then re-apply with this fix.

iluuu1994 added a commit that referenced this pull request Apr 30, 2025
This reverts commit 272f7f7.

Reverts GH-17712 for the PHP-8.4 branch. This will be reapplied later
with a fix for GH-18463 (GH-18464).
@iluuu1994
Copy link
Member

iluuu1994 commented Apr 30, 2025

@SakiTakamachi Please cherry-pick 386ab1d for 8.4.7RC2. We'll reapply the patch for the 8.4 branch for 8.4.8 with the proper fix in the coming days. Edit: And please also d991215.

Add recursion protection when emitting deprecation warnings for class
constants, since the deprecation message can come from an attribute that is
using the same constant for the message, or otherwise result in recursion.

But, internal constants are persisted, and thus cannot have recursion
protection. Otherwise, if a user error handler triggers bailout before the
recursion flag is removed then a subsequent request (e.g. with `--repeat 2`)
would start with that flag already applied. Internal constants can presumably
be trusted not to use deprecation messages that come from recursive attributes.

Fixes phpGH-18463
Fixes phpGH-17711
@DanielEScherzer DanielEScherzer changed the title GH-18463: skip recursion protection for internal constants Reapply GH-17712 with a fix for internal class constants Apr 30, 2025
@DanielEScherzer
Copy link
Member Author

@DanielEScherzer Sadly, you can't add them to the macros but you'll have to add it around them at call-site. Regardless, I think it's better to revert GH-17712 for now so that we can tag. I'll do that in approx. half an hour. We can then re-apply with this fix.

Okay, added around the call site - new patch reapplies yours with my fixes

SakiTakamachi pushed a commit that referenced this pull request May 1, 2025
This reverts commit 272f7f7.

Reverts GH-17712 for the PHP-8.4 branch. This will be reapplied later
with a fix for GH-18463 (GH-18464).
@SakiTakamachi
Copy link
Member

@SakiTakamachi Please cherry-pick 386ab1d for 8.4.7RC2. We'll reapply the patch for the 8.4 branch for 8.4.8 with the proper fix in the coming days. Edit: And please also d991215.

done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants