summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2022-12-04 13:58:23 +0100
committerYves Orton <demerphq@gmail.com>2022-12-05 14:52:09 +0100
commit73dbc8219374856b2b08baa76f8fbdef16c44ea0 (patch)
tree6dc65c76dbd584f6e32cc5c460af56a6bbb2923b /pp_ctl.c
parentd0a777fffcbb018434bd79aeb7c486a0f95595f1 (diff)
downloadperl-73dbc8219374856b2b08baa76f8fbdef16c44ea0.tar.gz
pp_ctl.c - copy hook into %INC not alias it
When an @INC hook is executed and it updates %INC it can result in @INC being updated and the hook being destroyed. This seems to be because the SV fetched from @INC is stored into %INC directly, essentially creating an alias (in perl terms) of the original. When the alias is updated, for instance by setting it to be a string, this is reflected in both @INC and %INC. By copying the sv before we store it we avoid this problem. We can't run the test under miniperl as it uses IO layers. This should fix GH #20577.
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 1e6dda7e98..fb760ee183 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4605,10 +4605,13 @@ S_require_file(pTHX_ SV *sv)
(void)hv_store(GvHVn(PL_incgv),
unixname, unixlen, newSVpv(tryname,0),0);
} else {
+ /* store the hook in the sv, note we have to *copy* hook_sv,
+ * we don't want modifications to it to change @INC - see GH #20577
+ */
SV** const svp = hv_fetch(GvHVn(PL_incgv), unixname, unixlen, 0);
if (!svp)
(void)hv_store(GvHVn(PL_incgv),
- unixname, unixlen, SvREFCNT_inc_simple(hook_sv), 0 );
+ unixname, unixlen, newSVsv(hook_sv), 0 );
}
/* Now parse the file */