diff options
author | Tony Cook <tony@develop-help.com> | 2022-11-17 14:41:35 +1100 |
---|---|---|
committer | James E Keenan <jkeenan@cpan.org> | 2022-11-18 18:12:45 -0500 |
commit | 970609e17c79578d2051de18f156f48701755715 (patch) | |
tree | d9de3ab70e16c64e9202bf197c299d514ecce8f8 | |
parent | 2e4090b82403991910f1fe64866048b62ccf5402 (diff) | |
download | perl-970609e17c79578d2051de18f156f48701755715.tar.gz |
change HvENAME_HEK() to HvENAME_HEK_NN() where NULLs would crash anyway
gcc 12 was producing a confusing message complaining that
references to with hek_key[] were beyond the end of the array,
even though a properly HEK has bytes beyond the first we declare.
From experimentation I theorize the confusing message was produced
because HvENAME_HEK() can return a NULL pointer, and the array
pointed to by any NULL pointer is zero length, producing the
array bounds warning we were seeing.
Fixed by changing each hv_(fetch|delete)hek() call to use the
HvENAME_HEK_NN() macro variant, which doesn't include an explicit
NULL return value.
mro_method_changed_in() was a bit special, it evaluated the
hv_fetchhek() before the check for an anonymous stash, so I reordered
the code to take advantage of C99, checking the assertions before we
dereference the stash pointer, checking we have a name before trying
to look it up.
-rw-r--r-- | hv.c | 8 | ||||
-rw-r--r-- | mro_core.c | 13 |
2 files changed, 11 insertions, 10 deletions
@@ -2286,8 +2286,8 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags) mro_isa_changed_in(hv); if (PL_stashcache) { DEBUG_o(Perl_deb(aTHX_ "hv_undef_flags clearing PL_stashcache for effective name '%" - HEKf "'\n", HEKfARG(HvENAME_HEK(hv)))); - (void)hv_deletehek(PL_stashcache, HvENAME_HEK(hv), G_DISCARD); + HEKf "'\n", HEKfARG(HvENAME_HEK_NN(hv)))); + (void)hv_deletehek(PL_stashcache, HvENAME_HEK_NN(hv), G_DISCARD); } } @@ -2300,8 +2300,8 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags) { if (name && PL_stashcache) { DEBUG_o(Perl_deb(aTHX_ "hv_undef_flags clearing PL_stashcache for name '%" - HEKf "'\n", HEKfARG(HvNAME_HEK(hv)))); - (void)hv_deletehek(PL_stashcache, HvNAME_HEK(hv), G_DISCARD); + HEKf "'\n", HEKfARG(HvNAME_HEK_NN(hv)))); + (void)hv_deletehek(PL_stashcache, HvNAME_HEK_NN(hv), G_DISCARD); } hv_name_set(hv, NULL, 0, flags); } diff --git a/mro_core.c b/mro_core.c index 2be181e102..3bd05af901 100644 --- a/mro_core.c +++ b/mro_core.c @@ -1327,17 +1327,18 @@ via, C<mro::method_changed_in(classname)>. void Perl_mro_method_changed_in(pTHX_ HV *stash) { - const char * const stashname = HvENAME_get(stash); - const STRLEN stashname_len = HvENAMELEN_get(stash); - - SV ** const svp = hv_fetchhek(PL_isarev, HvENAME_HEK(stash), 0); - HV * const isarev = svp ? MUTABLE_HV(*svp) : NULL; - PERL_ARGS_ASSERT_MRO_METHOD_CHANGED_IN; + const char * const stashname = HvENAME_get(stash); + if(!stashname) Perl_croak(aTHX_ "Can't call mro_method_changed_in() on anonymous symbol table"); + const STRLEN stashname_len = HvENAMELEN_get(stash); + + SV ** const svp = hv_fetchhek(PL_isarev, HvENAME_HEK_NN(stash), 0); + HV * const isarev = svp ? MUTABLE_HV(*svp) : NULL; + /* Inc the package generation, since a local method changed */ HvMROMETA(stash)->pkg_gen++; |