diff options
author | Yves Orton <demerphq@gmail.com> | 2022-11-25 20:05:24 +0100 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2022-12-09 18:34:58 +0100 |
commit | 901d80aa640b7a4bacdba6355b48343f30148c0b (patch) | |
tree | 21f1dc208a211e955b614a6ac03f6703dffc3b5b /pp_ctl.c | |
parent | c8b0222fe78d83d2c40d2141c264d0c1581429df (diff) | |
download | perl-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.c | 28 |
1 files changed, 21 insertions, 7 deletions
@@ -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); } } |