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.