summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2022-11-25 20:05:24 +0100
committerYves Orton <demerphq@gmail.com>2022-12-09 18:34:58 +0100
commit901d80aa640b7a4bacdba6355b48343f30148c0b (patch)
tree21f1dc208a211e955b614a6ac03f6703dffc3b5b /pp_ctl.c
parentc8b0222fe78d83d2c40d2141c264d0c1581429df (diff)
downloadperl-901d80aa640b7a4bacdba6355b48343f30148c0b.tar.gz
pp_ctl.c - require_file: truthful errors and tests: ties are called once
We need to keep track of what we actually checked. We cannot simply report the state of @INC at the end of the require, as it might have changed, possibly several times during the require. This also accounts for most "silly" stuff that might upset our internal assumptions, for instance where a tie might report one value to the code doing the directory check and another in the error message. We had long standing tests to see that @INC tie elements where called "once" but they actually tested they were called twice despite claiming otherwise. This fixes all of those test so that a tied @INC entry is called exactly once, and whatever it returned the first time is placed in the error message. This includes a change to the require error message, so that where it once said "@INC contains:" it now says "@INC entries checked:". Note this patch requires parent v0.239 to be available (which was done in the previous commit).
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 68ee99bd4a..618349f9a5 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4259,6 +4259,7 @@ S_require_file(pTHX_ SV *sv)
*
* For searchable paths, just search @INC normally
*/
+ AV *inc_checked = (AV*)sv_2mortal((SV*)newAV());
if (!tryrsfp && !(errno == EACCES && !path_searchable)) {
SSize_t inc_idx;
#ifdef VMS
@@ -4269,9 +4270,21 @@ S_require_file(pTHX_ SV *sv)
namesv = newSV_type(SVt_PV);
AV *inc_ar = GvAVn(PL_incgv);
for (inc_idx = 0; inc_idx <= AvFILL(inc_ar); inc_idx++) {
- SV * const dirsv = *av_fetch(inc_ar, inc_idx, TRUE);
+ SV *dirsv = *av_fetch(inc_ar, inc_idx, TRUE);
+
+ if (SvGMAGICAL(dirsv)) {
+ SvGETMAGIC(dirsv);
+ dirsv = newSVsv_nomg(dirsv);
+ } else {
+ /* on the other hand, since we aren't copying we do need
+ * to increment */
+ SvREFCNT_inc(dirsv);
+ }
+ if (!SvOK(dirsv))
+ continue;
+
+ av_push(inc_checked, dirsv);
- SvGETMAGIC(dirsv);
if (SvROK(dirsv)) {
int count;
SV **svp;
@@ -4536,14 +4549,15 @@ S_require_file(pTHX_ SV *sv)
DIE(aTHX_ "Can't locate %s: %s: %s",
name, tryname, Strerror(saved_errno));
} else {
- if (path_searchable) { /* did we lookup @INC? */
- AV * const ar = GvAVn(PL_incgv);
+ if (path_searchable) { /* did we lookup @INC? */
SSize_t i;
SV *const msg = newSVpvs_flags("", SVs_TEMP);
SV *const inc = newSVpvs_flags("", SVs_TEMP);
- for (i = 0; i <= AvFILL(ar); i++) {
+ for (i = 0; i <= AvFILL(inc_checked); i++) {
+ SV **svp= av_fetch(inc_checked, i, TRUE);
+ if (!svp || !*svp) continue;
sv_catpvs(inc, " ");
- sv_catsv(inc, *av_fetch(ar, i, TRUE));
+ sv_catsv(inc, *svp);
}
if (memENDPs(name, len, ".pm")) {
const char *e = name + len - (sizeof(".pm") - 1);
@@ -4597,7 +4611,7 @@ S_require_file(pTHX_ SV *sv)
/* diag_listed_as: Can't locate %s */
DIE(aTHX_
- "Can't locate %s in @INC%" SVf " (@INC contains:%" SVf ")",
+ "Can't locate %s in @INC%" SVf " (@INC entries checked:%" SVf ")",
name, msg, inc);
}
}