diff options
author | Nicholas Clark <nick@ccl4.org> | 2006-04-15 13:45:13 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2006-04-15 13:45:13 +0000 |
commit | 5675696b3881ef5bfde3012a829ca51ab1d42333 (patch) | |
tree | 8752f6d49bf11183e5a022fd217c6c5c87d96302 /pp_ctl.c | |
parent | bde61959ea5e52e421c597172a9aeac53357fcd9 (diff) | |
download | perl-5675696b3881ef5bfde3012a829ca51ab1d42333.tar.gz |
Add more tests for the builtin source filter implementation, and fix
two bugs - it would loop infinitely if data were already in the read
buffer, and it would process those data twice.
p4raw-id: //depot/perl@27812
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 18 |
1 files changed, 15 insertions, 3 deletions
@@ -4538,14 +4538,23 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) SV * const filter_state = (SV *)IoTOP_GV(datasv); SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv); int len = 0; - + /* Filter API says that the filter appends to the contents of the buffer. + Usually the buffer is "", so the details don't matter. But if it's not, + then clearly what it contains is already filtered by this filter, so we + don't want to pass it in a second time. + I'm going to use a mortal in case the upstream filter croaks. */ + SV *const upstream + = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv)) + ? sv_newmortal() : buf_sv; + + SvUPGRADE(upstream, SVt_PV); /* I was having segfault trouble under Linux 2.2.5 after a parse error occured. (Had to hack around it with a test for PL_error_count == 0.) Solaris doesn't segfault -- not sure where the trouble is yet. XXX */ if (filter_has_file) { - len = FILTER_READ(idx+1, buf_sv, maxlen); + len = FILTER_READ(idx+1, upstream, maxlen); } if (filter_sub && len >= 0) { @@ -4557,7 +4566,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) SAVETMPS; EXTEND(SP, 2); - DEFSV = buf_sv; + DEFSV = upstream; PUSHMARK(SP); PUSHs(sv_2mortal(newSViv(maxlen))); if (filter_state) { @@ -4596,6 +4605,9 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) filter_del(S_run_user_filter); } + if (upstream != buf_sv) { + sv_catsv(buf_sv, upstream); + } return len; } |