-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
ReflectionClass::isInstantiable() is wrong about internal classes that prevent instantiation #17796
Comments
I disagree with the proposal. We are limited in bit flags that we can use and assign. This is also a more generic problem and affects many areas of the codebase. The reason is that instantiation is not determined just by "compile time" known information but depends on a call to the This is only ever overloaded by internal classes that prevent instantiation and have a custom error message. IMHO the simpler and more generic solution is to convert those classes to use a private constructor and get rid of the |
Is there anything stopping us from making the constructor private in these cases, and circumventing this internally when constructing the objects?
We'll have to solve this eventually anyway. I did so in #13886 but it showed a significant increase in instruction count by Valgrind. We should check if this has a real-world impact. This may be caused by growing data structure, or less performant flag comparison, I'm not sure. Depending on the outcome, we can decide:
|
Hmm, I didn't realize that all overloads were just to report an error, but that is what github search reports. What about just having |
Not that I am aware off, and I don't think we necessarily need a custom error message. Would also make documentation more explicit IMHO on the php.net side. I was planning on doing this soon-ish, but if @DanielEScherzer wants to do this I'm fhappy to let them do it (as its not that difficult either :) ) |
I agree with getting rid of the get_constructor trick an using private constructors. These private constructors still will need to throw though as they can be called via reflection, ignoring the visibility. I wasn't sure what you meant with "circumventing this internally", just wanted to point out the visibility escape hatch. |
AFAIK any internal object cannot be instantiated by Reflection. Am I mistaken? |
That's wrong. Here's an example btw where we call Dom\Node's private __construct function: credits to #16190 where I learned you can do this |
Probably the easiest solution is to prevent reflection from instantiating internal classes... but don't know how much that will break. |
At one point, this was more or less the case, but the constraint was relaxed in d586441 |
Sounds good to me. Should I try and send one patch to update all of the extensions that currently use that get_constructor trick? Or would it be better to split them up (more patches to review but easier individually and less likely to get merge conflicts)? |
Probably separate PRs, one for each ext, as otherwise we get a lot of codeowner review requests from a single PR and some parts may be already approved while others still waiting, which causes this weird effect where some parts could already be merged and some not. |
I overall agree with the fact that we should get rid of these rejecting |
Sounds like a great idea to add such an attribute - but maybe I have a mostly working implementation of |
Although it's worth noting that this only calls a constructor on an already constructed object, rather than constructing a new one, so it's not actually problematic. If the constructor were private and empty, calling it would simply do nothing. As Bob mentioned, one issue that remains is that we get a worse, generic error message ( |
I've sent #17846 to demonstrate how an attribute can provide the missing information. If there is any support for it I'll look into drafting an RFC |
Test script:
Failures
For each of the following classes,
ReflectionClass::isInstantiable()
returns true, but trying to create an instance of the class directly fails:Not all of these extensions are on 3v4l but those that are can be confirmed at https://3v4l.org/BmAkH
I didn't test all extensions, what I have enabled locally is:
Proposal
I propose that we add a new class flag,
ZEND_ACC_NON_INSTANTIABLE
, that classes can apply when they are registered.PHP Version
65d4331
The text was updated successfully, but these errors were encountered: