diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-10-25 06:15:30 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-10-25 08:15:14 -0700 |
commit | 5a2bc23bfe5dc60ff957cb44ffaa57668d56d238 (patch) | |
tree | ae34e806720633a0e8591308baec84f0bfb1ff6d /ext/PerlIO-scalar | |
parent | f6d098c6aa26a223a4250725da6a7784102e19a6 (diff) | |
download | perl-5a2bc23bfe5dc60ff957cb44ffaa57668d56d238.tar.gz |
Better fix for #119529
<$fh> used to loop if $fh was opened to an in-memory handle containing
a reference.
Commit 552908b174 fixed the loop by forcing a reference to a string
when the handle was created. It did not take into account that the
reference might be read-only. It was also insufficient, in that
the target scalar could be set to a reference after the handle
was created.
The real reason it was looping was that the code for returning and
setting the size of the buffer was not handling non-PVs properly
(unless they were globs, which were special-cased). It might return
0, and it might not, depending on what the internal SV field hap-
pened to hold.
This caused looping under 5.12 and onwards, but even in 5.10 <$fh>
returned nothing.
In this case, deleting code makes things just work.
Reverting the hunk from 552908b174 stops appending to refs from work-
ing, so I tweaked PerlIOScalar_pushed to fix that (which also reduced
the amount of code).
Diffstat (limited to 'ext/PerlIO-scalar')
-rw-r--r-- | ext/PerlIO-scalar/scalar.xs | 20 | ||||
-rw-r--r-- | ext/PerlIO-scalar/t/scalar.t | 15 |
2 files changed, 17 insertions, 18 deletions
diff --git a/ext/PerlIO-scalar/scalar.xs b/ext/PerlIO-scalar/scalar.xs index 95668e7a2c..fd8ac67d4b 100644 --- a/ext/PerlIO-scalar/scalar.xs +++ b/ext/PerlIO-scalar/scalar.xs @@ -48,11 +48,7 @@ PerlIOScalar_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, else { s->var = newSVpvn("", 0); } - if (SvROK(s->var)) - /* force refs, overload etc to be plain strings */ - (void)SvPV_force_nomg_nolen(s->var); - else - SvUPGRADE(s->var, SVt_PV); + SvUPGRADE(s->var, SVt_PV); code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab); if (!SvOK(s->var) || (PerlIOBase(f)->flags) & PERLIO_F_TRUNCATE) @@ -69,10 +65,7 @@ PerlIOScalar_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, return -1; } if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND) - { - sv_force_normal(s->var); - s->posn = SvCUR(s->var); - } + s->posn = sv_len(s->var); else s->posn = 0; SvSETMAGIC(s->var); @@ -270,10 +263,7 @@ PerlIOScalar_get_cnt(pTHX_ PerlIO * f) if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) { PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); STRLEN len; - SvGETMAGIC(s->var); - if (isGV_with_GP(s->var)) - (void)SvPV(s->var,len); - else len = SvCUR(s->var); + (void)SvPV(s->var,len); if (len > (STRLEN) s->posn) return len - (STRLEN)s->posn; else @@ -299,9 +289,7 @@ PerlIOScalar_set_ptrcnt(pTHX_ PerlIO * f, STDCHAR * ptr, SSize_t cnt) PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar); STRLEN len; PERL_UNUSED_ARG(ptr); - SvGETMAGIC(s->var); - if (isGV_with_GP(s->var)) (void)SvPV(s->var,len); - else len = SvCUR(s->var); + (void)SvPV(s->var,len); s->posn = len - cnt; } diff --git a/ext/PerlIO-scalar/t/scalar.t b/ext/PerlIO-scalar/t/scalar.t index f5ee47e471..4de54f7ed0 100644 --- a/ext/PerlIO-scalar/t/scalar.t +++ b/ext/PerlIO-scalar/t/scalar.t @@ -16,7 +16,7 @@ use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END); # Not 0, 1, 2 everywhere. $| = 1; -use Test::More tests => 109; +use Test::More tests => 112; my $fh; my $var = "aaa\n"; @@ -463,11 +463,22 @@ my $byte_warning = "Strings with code points over 0xFF may not be mapped into in is_deeply(\@warnings, [ $byte_warning ], "check warning"); } -# RT #119529: non-string should be forced into a string +# RT #119529: Reading refs should not loop { my $x = \42; open my $fh, "<", \$x; my $got = <$fh>; # this used to loop like($got, qr/^SCALAR\(0x[0-9a-f]+\)$/, "ref to a ref"); + is ref $x, "SCALAR", "target scalar is still a reference"; +} + +# Appending to refs +{ + my $x = \42; + my $as_string = "$x"; + open my $refh, ">>", \$x; + is ref $x, "SCALAR", 'still a ref after opening for appending'; + print $refh "boo\n"; + is $x, $as_string."boo\n", 'string gets appended to ref'; } |