Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 300daee

Browse files
committed
readdir() etc: better warning if called on handle open()ed as file
Fixes #22394
1 parent d6b3d83 commit 300daee

File tree

6 files changed

+72
-40
lines changed

6 files changed

+72
-40
lines changed

embed.fnc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5089,6 +5089,8 @@ S |OP * |doform |NN CV *cv \
50895089
|NULLOK OP *retop
50905090
S |SV * |space_join_names_mortal \
50915091
|NULLOK char * const *array
5092+
S |void |warn_not_dirhandle \
5093+
|NN GV *gv
50925094
# if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
50935095
RS |int |dooneliner |NN const char *cmd \
50945096
|NN const char *filename

embed.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,7 @@
15961596
# if defined(PERL_IN_PP_SYS_C)
15971597
# define doform(a,b,c) S_doform(aTHX_ a,b,c)
15981598
# define space_join_names_mortal(a) S_space_join_names_mortal(aTHX_ a)
1599+
# define warn_not_dirhandle(a) S_warn_not_dirhandle(aTHX_ a)
15991600
# if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
16001601
# define dooneliner(a,b) S_dooneliner(aTHX_ a,b)
16011602
# endif

pod/perldiag.pod

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,20 @@ version.
674674
(F) A subroutine invoked from an external package via call_sv()
675675
exited by calling exit.
676676

677+
=item %s() attempted on invalid dirhandle %s
678+
679+
(W io) You called readdir(), telldir(), seekdir(), rewinddir() or
680+
closedir() on a handle that has not been opened, or is now closed. A
681+
handle must be successfully opened with opendir() to be used with
682+
these functions. Check your control flow.
683+
684+
=item %s() attempted on handle %s opened with open()
685+
686+
(W io) You called readdir(), telldir(), seekdir(), rewinddir() or
687+
closedir() on a handle that was opened with open(). If you want to
688+
use these functions to traverse the contents of a directory, you need
689+
to open the handle with opendir().
690+
677691
=item %s() called too early to check prototype
678692

679693
(W prototype) You've called a function that has a prototype before the
@@ -1883,11 +1897,6 @@ keyword.
18831897

18841898
(F) Creating a new thread inside the C<s///> operator is not supported.
18851899

1886-
=item closedir() attempted on invalid dirhandle %s
1887-
1888-
(W io) The dirhandle you tried to close is either closed or not really
1889-
a dirhandle. Check your control flow.
1890-
18911900
=item close() on unopened filehandle %s
18921901

18931902
(W unopened) You tried to close a filehandle that was never opened.
@@ -5646,11 +5655,6 @@ range, and at least one of the end points is a decimal digit. Under the
56465655
stricter rules, when this happens, both end points should be digits in
56475656
the same group of 10 consecutive digits.
56485657

5649-
=item readdir() attempted on invalid dirhandle %s
5650-
5651-
(W io) The dirhandle you're reading from is either closed or not really
5652-
a dirhandle. Check your control flow.
5653-
56545658
=item readline() on closed filehandle %s
56555659

56565660
(W closed) The filehandle you're reading from got itself closed sometime
@@ -5851,11 +5855,6 @@ for the character.
58515855
(W syntax) You wrote your assignment operator backwards. The = must
58525856
always come last, to avoid ambiguity with subsequent unary operators.
58535857

5854-
=item rewinddir() attempted on invalid dirhandle %s
5855-
5856-
(W io) The dirhandle you tried to do a rewinddir() on is either closed
5857-
or not really a dirhandle. Check your control flow.
5858-
58595858
=item Scalars leaked: %d
58605859

58615860
(S internal) Something went wrong in Perl's internal bookkeeping
@@ -5905,11 +5904,6 @@ construct, not just the empty search pattern. Therefore code written
59055904
in Perl 5.10.0 or later that uses the // as the I<defined-or> can be
59065905
misparsed by pre-5.10.0 Perls as a non-terminated search pattern.
59075906

5908-
=item seekdir() attempted on invalid dirhandle %s
5909-
5910-
(W io) The dirhandle you are doing a seekdir() on is either closed or not
5911-
really a dirhandle. Check your control flow.
5912-
59135907
=item %sseek() on unopened filehandle
59145908

59155909
(W unopened) You tried to use the seek() or sysseek() function on a
@@ -6494,11 +6488,6 @@ know about your kind of stdio. You'll have to use a filename instead.
64946488
(F) You tried to use C<goto> to reach a label that was too deeply nested
64956489
for Perl to reach. Perl is doing you a favor by refusing.
64966490

6497-
=item telldir() attempted on invalid dirhandle %s
6498-
6499-
(W io) The dirhandle you tried to telldir() is either closed or not really
6500-
a dirhandle. Check your control flow.
6501-
65026491
=item tell() on unopened filehandle
65036492

65046493
(W unopened) You tried to use the tell() function on a filehandle that

pp_sys.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,6 +4285,23 @@ PP_wrapped(pp_open_dir, 2, 0)
42854285
#endif
42864286
}
42874287

4288+
static void
4289+
S_warn_not_dirhandle(pTHX_ GV *gv) {
4290+
IO *io = GvIOn(gv);
4291+
4292+
if (IoIFP(io)) {
4293+
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4294+
"%s() attempted on handle %" HEKf
4295+
" opened with open()",
4296+
OP_DESC(PL_op), HEKfARG(GvENAME_HEK(gv)));
4297+
}
4298+
else {
4299+
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4300+
"%s() attempted on invalid dirhandle %" HEKf,
4301+
OP_DESC(PL_op), HEKfARG(GvENAME_HEK(gv)));
4302+
}
4303+
}
4304+
42884305
PP_wrapped(pp_readdir, 1, 0)
42894306
{
42904307
#if !defined(Direntry_t) || !defined(HAS_READDIR)
@@ -4302,9 +4319,7 @@ PP_wrapped(pp_readdir, 1, 0)
43024319
IO * const io = GvIOn(gv);
43034320

43044321
if (!IoDIRP(io)) {
4305-
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4306-
"readdir() attempted on invalid dirhandle %" HEKf,
4307-
HEKfARG(GvENAME_HEK(gv)));
4322+
warn_not_dirhandle(gv);
43084323
goto nope;
43094324
}
43104325

@@ -4352,9 +4367,7 @@ PP_wrapped(pp_telldir, 1, 0)
43524367
IO * const io = GvIOn(gv);
43534368

43544369
if (!IoDIRP(io)) {
4355-
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4356-
"telldir() attempted on invalid dirhandle %" HEKf,
4357-
HEKfARG(GvENAME_HEK(gv)));
4370+
warn_not_dirhandle(gv);
43584371
goto nope;
43594372
}
43604373

@@ -4378,9 +4391,7 @@ PP_wrapped(pp_seekdir, 2, 0)
43784391
IO * const io = GvIOn(gv);
43794392

43804393
if (!IoDIRP(io)) {
4381-
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4382-
"seekdir() attempted on invalid dirhandle %" HEKf,
4383-
HEKfARG(GvENAME_HEK(gv)));
4394+
warn_not_dirhandle(gv);
43844395
goto nope;
43854396
}
43864397
(void)PerlDir_seek(IoDIRP(io), along);
@@ -4403,9 +4414,7 @@ PP_wrapped(pp_rewinddir, 1, 0)
44034414
IO * const io = GvIOn(gv);
44044415

44054416
if (!IoDIRP(io)) {
4406-
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4407-
"rewinddir() attempted on invalid dirhandle %" HEKf,
4408-
HEKfARG(GvENAME_HEK(gv)));
4417+
warn_not_dirhandle(gv);
44094418
goto nope;
44104419
}
44114420
(void)PerlDir_rewind(IoDIRP(io));
@@ -4427,9 +4436,7 @@ PP_wrapped(pp_closedir, 1, 0)
44274436
IO * const io = GvIOn(gv);
44284437

44294438
if (!IoDIRP(io)) {
4430-
Perl_ck_warner(aTHX_ packWARN(WARN_IO),
4431-
"closedir() attempted on invalid dirhandle %" HEKf,
4432-
HEKfARG(GvENAME_HEK(gv)));
4439+
warn_not_dirhandle(gv);
44334440
goto nope;
44344441
}
44354442
#ifdef VOID_CLOSEDIR

proto.h

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

t/op/readdir.t

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,32 @@ SKIP:
8686
is($errno, 0, "errno preserved");
8787
}
8888

89+
SKIP:
90+
{
91+
open my $fh, "<", "op"
92+
or skip "can't open a directory on this platform", 10;
93+
my $warned;
94+
local $SIG{__WARN__} = sub { $warned = "@_" };
95+
ok(!readdir($fh), "cannot readdir file handle");
96+
like($warned, qr/readdir\(\) attempted on handle \$fh opened with open/,
97+
"check the message");
98+
undef $warned;
99+
ok(!telldir($fh), "cannot telldir file handle");
100+
like($warned, qr/telldir\(\) attempted on handle \$fh opened with open/,
101+
"check the message");
102+
undef $warned;
103+
ok(!seekdir($fh, 0), "cannot seekdir file handle");
104+
like($warned, qr/seekdir\(\) attempted on handle \$fh opened with open/,
105+
"check the message");
106+
undef $warned;
107+
ok(!rewinddir($fh), "cannot rewinddir file handle");
108+
like($warned, qr/rewinddir\(\) attempted on handle \$fh opened with open/,
109+
"check the message");
110+
undef $warned;
111+
ok(!closedir($fh), "cannot closedir file handle");
112+
like($warned, qr/closedir\(\) attempted on handle \$fh opened with open/,
113+
"check the message");
114+
undef $warned;
115+
}
116+
89117
done_testing();

0 commit comments

Comments
 (0)