summaryrefslogtreecommitdiff
path: root/ext/PerlIO-scalar
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-10-25 06:15:30 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-10-25 08:15:14 -0700
commit5a2bc23bfe5dc60ff957cb44ffaa57668d56d238 (patch)
treeae34e806720633a0e8591308baec84f0bfb1ff6d /ext/PerlIO-scalar
parentf6d098c6aa26a223a4250725da6a7784102e19a6 (diff)
downloadperl-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.xs20
-rw-r--r--ext/PerlIO-scalar/t/scalar.t15
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';
}