Make PerlIO::encoding more resilient to buffer changes
authorFather Chrysostomos <sprout@cpan.org>
Fri, 5 Oct 2012 04:56:00 +0000 (21:56 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 5 Oct 2012 13:13:09 +0000 (06:13 -0700)
commit667763bdbf37a30596512ca0a08a720d86c7e2a8
tree75605631198968fa4d4aa1518a67b9e044214ccb
parent0c38a575805726e13941c02d1cdf5b6b5c4ded11
Make PerlIO::encoding more resilient to buffer changes

I was trying to figure out why Encode’s perlio.t was sometimes failing
under PERL_OLD_COPY_ON_WRITE (depending on the number of comments in
the source code, or metereological conditions).

I noticed that PerlIO::encoding assumes that the buffer passed to
the encode method will come back SvPOKp.  (It accesses SvCUR without
checking any flags.)

That means it can come back as a typeglob, reference, or undefined,
and PerlIO::encoding won’t care.  This can result in crashes.  Assign-
ing $_[1] = *foo inside an encode method is not a smart thing to do,
but it shouldn’t crash.

PerlIO::encoding was also assuming that SvPVX would not change between
calls to encode.  It is very easy to reallocate it.  This means the
internal buffer used by the encoding layer (which is owned by the
SV buffer passed to the encode method) can be freed and still subse-
quently written too, which is not good.

This commit makes PerlIO::encoding force stringification of the value
returned.  If it does not match its internal buffer pointers, it
resets them based on the buffer SV.

This probably makes Encode pass its tests under
PERL_OLD_COPY_ON_WRITE, but I have yet to confirm it.  Encoding mod-
ules are expected to write to the buffer ($_[1] = '') in certain
cases.  If COW is enabled, that would cause the buffer’s SvPVX to
point to the same string as the rhs, which would explain why the lack
of accounting for SvPVX changes caused test failures under
PERL_OLD_COPY_ON_WRITE.
ext/PerlIO-encoding/encoding.xs
ext/PerlIO-encoding/t/encoding.t