diff options
author | Yves Orton <demerphq@gmail.com> | 2022-03-03 15:24:03 +0100 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2022-03-07 16:22:12 +0100 |
commit | 8b03aeb95ab72abdb2fa40f2d1196ce42f34708d (patch) | |
tree | 5ec32d32dc62e922697511b5404d9440d7ea006e | |
parent | 7ea8b04b5a0e6952b7ffd5a8fd96468b72da6bea (diff) | |
download | perl-8b03aeb95ab72abdb2fa40f2d1196ce42f34708d.tar.gz |
Fix GH Issue #19472: read warnings from open($fh,">",\(my $x))
We produce all kinds of warnings if someone opens a scalar reference
that is undef. Prior to this we handled write operations ok, at
least in blead, but read operations would produce a plethora of
warnings. To me this analogous to treating an undef var as hash
and trying to read from it, we autovivify the undef var to be
a hash. So in this case we should just "autovivify" the referenced
scalar to be an empty string.
Eg. before this patch:
./perl -Ilib -wle'open my $fh,"+>", \(my $v); my @x=<$fh>; print 0+@x'
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
Use of uninitialized value $fh in <HANDLE> at -e line 1.
0
After it:
./perl -Ilib -wle'open my $fh,"+>", \(my $v); my @x=<$fh>; print 0+@x'
0
-rw-r--r-- | doio.c | 10 | ||||
-rw-r--r-- | pod/perlfunc.pod | 12 | ||||
-rw-r--r-- | t/io/open.t | 24 |
3 files changed, 43 insertions, 3 deletions
@@ -639,6 +639,16 @@ Perl_do_open6(pTHX_ GV *gv, const char *oname, STRLEN len, goto say_false; } #endif /* USE_STDIO */ + if (SvROK(*svp) && !sv_isobject(*svp)) { + /* if they pass in a reference and its not an object + * and the reference is to undef, "autovivify" it to + * the empty string. See GH Issue #19472 + */ + SV *sv= SvRV(*svp); + if (!SvOK(sv) && !SvREADONLY(sv)) + sv_setpvs(MUTABLE_SV(sv),""); + } + p = (SvOK(*svp) || SvGMAGICAL(*svp)) ? SvPV(*svp, nlen) : NULL; if (p && !IS_SAFE_PATHNAME(p, nlen, "open")) { diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 26d59a580e..1950e95cd0 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -4657,8 +4657,8 @@ L<C<seek>|/seek FILEHANDLE,POSITION,WHENCE> to do the reading. =item Opening a filehandle into an in-memory scalar You can open filehandles directly to Perl scalars instead of a file or -other resource external to the program. To do so, provide a reference to -that scalar as the third argument to C<open>, like so: +other resource external to the program. To do so, provide an unblessed +reference to that scalar as the third argument to C<open>, like so: open(my $memory, ">", \$var) or die "Can't open memory file: $!"; @@ -4674,6 +4674,14 @@ The scalars for in-memory files are treated as octet strings: unless the file is being opened with truncation the scalar may not contain any code points over 0xFF. +Be aware that attempting to open a reference to a readonly scalar will +cause a warning and the open to fail. + +Prior to Perl version 5.36.0, passing in a reference to an undef scalar +could cause strange warnings. As of Perl version 5.36.0, provided the +reference is unblessed, the scalar will be "autovivified" to be an empty +string, even for read mode open operations. + Opening in-memory files I<can> fail for a variety of reasons. As with any other C<open>, check the return value for success. diff --git a/t/io/open.t b/t/io/open.t index 7fa492342d..86ca8a8498 100644 --- a/t/io/open.t +++ b/t/io/open.t @@ -10,7 +10,7 @@ $| = 1; use warnings; use Config; -plan tests => 188; +plan tests => 193; sub ok_cloexec { SKIP: { @@ -410,6 +410,28 @@ SKIP: { or unlink \*STDOUT; } +# [GH Issue #19472] Opening a reference to an undef scalar +SKIP: { + skip_if_miniperl("no dynamic loading on miniperl, so can't load PerlIO::scalar", 5); + use strict; + my $var; + open my $fh, "+>", \$var; + is defined($var) ? "defined" : "undef", "defined", + '[GH Issue #19472]: open $fh, ">", \$undef_var leaves var defined'; + is $var, "", + '[GH Issue #19472]: open $fh, ">", \$undef_var leaves var empty string'; + my $warn_count= 0; + my $warn_text= ""; + local $SIG{__WARN__}= sub { $warn_count++; $warn_text .= shift; }; + my @x= <$fh>; + is $warn_count, 0, '[GH Issue #19472]: read after open $fh, ">", ' . + '\$undef_var produces 0 warnings'; + is $warn_text, "", '[GH Issue #19472]: read after open $fh, ">", ' . + '\$undef_var produces no warning text'; + is 0+@x, 0, '[GH Issue #19472]: <$fh> after open $fh, ">", ' . + '\$undef_var returns nothing'; +} + # check that we can call methods on filehandles auto-magically # and have IO::File loaded for us SKIP: { |