summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorRichard Leach <richardleach@users.noreply.github.com>2022-08-25 00:10:10 +0000
committerRichard Leach <richardleach@users.noreply.github.com>2022-09-14 21:15:46 +0100
commit658a5bedcfb012a503b61de6c8cb69924cc6f6f8 (patch)
tree71f0eb663783b090025e2b41cc28b3aee092c33f /sv.c
parenta62862a6bb77ef3d3d6645fd9026e4dacc1888e6 (diff)
downloadperl-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.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/sv.c b/sv.c
index a7a004400d..538944dfb3 100644
--- a/sv.c
+++ b/sv.c
@@ -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);