Hide most KEY_* symbols outside core - #24796
khwilliamson wants to merge 15 commits into
Conversation
|
I don't like this. Now, to get the same effect, you have to say #define PERL_CORE
#include "keywords.h"What's the point of requiring two preprocessor directives instead of one? |
01ef19b to
525b9b8
Compare
The module shouldn't be including our internal header in the first place. Yes it can cheat, and that second directive makes it painfully obvious that that is what is going on. That's the point. To make it harder to inadvertently gain access to our internals. @mauke previously wrote
There are at least two reasons to limit the visibility of symbols.
I hadn't appreciated that this header wasn't always exposed to the outside. So yes, the status quo isn't as bad as I had thought. But there has been agreement in the first pull request and no dissension at that time that these symbols are for internal use by the core. A few have leaked out, and this PR accommodates those, while limiting the spread. (I don't understand enough about XS to know if this adversely affects XS::Parse::Keyword. If it does I will submit a PR to correct that.) |
|
I don't think it's needed - keywords.h is opt in, the names are only exposed if the user explicitly pulls them in. |
|
@tonycoz I dont think that addresses the concern that @khwilliamson expressed, we don't want people to use these files really, we could change them in any way at any time, and since we cant really stop them we want them to acknowledge that they are doing something dodgy when they do. So I vote yes for this patch, although id make it something like: and not We keep saying we cant fix our internals because too much CPAN XS code depends on our current API, which means we should do everything we can to reduce our expose and increase our degrees of flexibility. |
I don't think we need another level of "you're depending on the implementation - beware the alligators!" - we already warn about this in perlguts:
Adding another name just means we didn't really mean it for I just don't see that much reason to add the additional check. |
| #if defined(USE_REENTRANT_API) && defined(HAS_GETSPNAM_R) | ||
| case 's': | ||
| if (name[4] == 'p' && | ||
| name[5] == 'n' && | ||
| name[6] == 'a' && | ||
| name[7] == 'm') | ||
| { /* getspnam */ | ||
| return KEY_getspnam; | ||
| } | ||
|
|
||
| goto unknown; | ||
| #endif /* defined(USE_REENTRANT_API) && defined(HAS_GETSPNAM_R) */ |
There was a problem hiding this comment.
Do we ever actually want to parse this as a keyword?
There was a problem hiding this comment.
Yes. The commit 93452d4 (this PR) removes that
There was a problem hiding this comment.
Why parse it as a keyword? (and it does get parsed, but then discarded)
There was a problem hiding this comment.
reentr.c calls Perl_keyword(), and has a case for KEY_getspnam.
In blead, reentr.c knows that this keyword isn't returned, so has a special conditional to work around that. But perl.h also has a fake keyword KEY_sigvar. And the authors of both symbols created them with the same value, so that seeing that value is ambiguous. This may work now by coincidence, but it is brittle. The easiest way to solve this now and keep it from happening in the future is to slightly modify the existing infrastructure to allow fake keywords, and allow its existing implementation to choose unique values for each. This prevents future collisions and fixes the current one.
I presumed that code that switched on the return of Perl_keyword() had a default: case to cover the cases where something got returned that it didn't handle, but I see a couple of cases with no default. That seems brittle and potentially already buggy in blead.
525b9b8 to
4933bba
Compare
4933bba to
51e5c29
Compare
Co-authored-by: Eric Herman <eric@freesa.org>
This commit extends the keyword specification syntax to allow a C preprocessor condition to restrict if a keyword is recognized or not, It merely passes the condition to Devel::Tokenizer::C which has the capability to handle it; we just weren't using that. This commit does not actually use this new ability.
Prior to this commit, if an entry in <DATA> had a strength of blank, the return was the negative of the keyword's value. Since the only such entry had a value of 0, this was not an issue. But the next commit will add an entry where it does matter. This also adds a commment that points out that a blank strength is interpreted as the symbol isn't actually a general keyword that an OP would need to be generated for.
This fake keyword is used only by the reentrant.c area of perl
It now has the ability to handle "fake" keywords.
These symbols are supposed to be of little interest outside the perl core, but a few have leaked out. This commit limits the visibility of all but those few.
51e5c29 to
63770b6
Compare
It would have been better to originally make PERL_CORE a longer symbol; but I agree that we can't really change it now. I do feel fairly strongly about requiring PERL_CORE to gain access to these symbols. I can foresee someone deciding that this header needs to be pulled in by perl.h, and then these symbols suddenly and silently become visible, including any that conflict, such as KEY_END does. And the other two headers that have lots of symbols and aren't currently pulled in by perl.h already have guards, regcomp.h and feature.h. That makes keywords.h the exception, to an admittedly small sample size. But the precedent is there to limit the visibility of symbols that aren't by-default exposed to the average XS module. |
This is a replacement for reverted 49fb862
It changes keywords.h to use #if's to limit the visibility of the symbols contained within it that don't need to be exported.
In researching this, I discovered that we had two different KEY_ symbols that evaluated to the same value, creating a potential clash. This was because these were non-standard uses for this mechanism. Since it is too easy for that to arise again, I enhanced the generating script to be able to handle non-standard ones, and folded those into it.