summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-04-15 13:45:13 +0000
committerNicholas Clark <nick@ccl4.org>2006-04-15 13:45:13 +0000
commit5675696b3881ef5bfde3012a829ca51ab1d42333 (patch)
tree8752f6d49bf11183e5a022fd217c6c5c87d96302 /pp_ctl.c
parentbde61959ea5e52e421c597172a9aeac53357fcd9 (diff)
downloadperl-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.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 7beea6abb3..364a1d5052 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -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;
}