diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-25 00:10:10 +0000 |
---|---|---|
committer | Richard Leach <richardleach@users.noreply.github.com> | 2022-09-14 21:15:46 +0100 |
commit | 658a5bedcfb012a503b61de6c8cb69924cc6f6f8 (patch) | |
tree | 71f0eb663783b090025e2b41cc28b3aee092c33f /sv.c | |
parent | a62862a6bb77ef3d3d6645fd9026e4dacc1888e6 (diff) | |
download | perl-658a5bedcfb012a503b61de6c8cb69924cc6f6f8.tar.gz |
Perl_sv_setsv_flags: return after invlist_clone case
In the "first_ switch" statement in Perl_sv_setsv_flags, there's this case:
case SVt_INVLIST:
invlist_clone(ssv, dsv);
break;
When the INVLIST code was added, it was unclear whether the logic following
that switch needed to apply to INVLISTs or not. Early returns were also seen
as risky from a future maintenance perspective. As a precaution, this case
was written to `break` rather than `return`.
With later analysis though, it seems like the code below this switch does
not apply to INVLISTs, apart from one unintended interaction.
* invlist_clone() - in regcomp.c - copies the PV buffer of ssv to dsv.
* However, whenever an invlist is initialized, SvPOK_on is called on its SV;
according to the nearby comment "/* This allows B to extract the PV */".
* Because the switch case does not return, the later `if (sflags & SVp_POK)`
branch will try to swipe/cow/copy the PV buffer of ssv to dsv. This is an
unnecessary double copy.
On that analysis, this commit changes the break into a return.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 6 |
1 files changed, 4 insertions, 2 deletions
@@ -4156,7 +4156,9 @@ Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags) SV_CHECK_THINKFIRST_COW_DROP(dsv); dtype = SvTYPE(dsv); /* THINKFIRST may have changed type */ - /* There's a lot of redundancy below but we're going for speed here */ + /* There's a lot of redundancy below but we're going for speed here + * Note: some of the cases below do return; rather than break; so the + * if-elseif-else logic below this switch does not see all cases. */ switch (stype) { case SVt_NULL: @@ -4244,7 +4246,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dsv, SV* ssv, const I32 flags) case SVt_INVLIST: invlist_clone(ssv, dsv); - break; + return; default: { const char * const type = sv_reftype(ssv,0); |