Re: [perl #41442] segfault (dead loop) with Encoding, use open :locale, print STDERR
Slaven Rezic [Mon, 5 Feb 2007 23:04:07 +0000 (00:04 +0100)]
Message-ID: <87veiggt2g.fsf@biokovo.herceg.de>

p4raw-id: //depot/perl@30213

MANIFEST
ext/PerlIO/encoding/encoding.pm
ext/PerlIO/encoding/encoding.xs
ext/PerlIO/encoding/t/nolooping.t [new file with mode: 0644]

index 760c921..4187452 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -933,6 +933,7 @@ ext/PerlIO/encoding/encoding.pm     PerlIO::encoding
 ext/PerlIO/encoding/encoding.xs        PerlIO::encoding
 ext/PerlIO/encoding/Makefile.PL        PerlIO::encoding makefile writer
 ext/PerlIO/encoding/MANIFEST   PerlIO::encoding list of files
+ext/PerlIO/encoding/t/nolooping.t      Tests for PerlIO::encoding
 ext/PerlIO/scalar/Makefile.PL  PerlIO layer for scalars
 ext/PerlIO/scalar/scalar.pm    PerlIO layer for scalars
 ext/PerlIO/scalar/scalar.xs    PerlIO layer for scalars
index c99e70b..dcc65f9 100644 (file)
@@ -1,7 +1,7 @@
 package PerlIO::encoding;
 
 use strict;
-our $VERSION = '0.09';
+our $VERSION = '0.10';
 our $DEBUG = 0;
 $DEBUG and warn __PACKAGE__, " called by ", join(", ", caller), "\n";
 
index 362d66c..617842f 100644 (file)
@@ -48,6 +48,7 @@ typedef struct {
     SV *enc;                   /* the encoding object */
     SV *chk;                    /* CHECK in Encode methods */
     int flags;                 /* Flags currently just needs lines */
+    int inEncodeCall;          /* trap recursive encode calls */
 } PerlIOEncode;
 
 #define NEEDS_LINES    1
@@ -147,6 +148,7 @@ PerlIOEncode_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, PerlIO_funcs *
     }
 
     e->chk = newSVsv(get_sv("PerlIO::encoding::fallback", 0));
+    e->inEncodeCall = 0;
 
     FREETMPS;
     LEAVE;
@@ -404,6 +406,7 @@ PerlIOEncode_flush(pTHX_ PerlIO * f)
        STRLEN len;
        SSize_t count = 0;
        if ((PerlIOBase(f)->flags & PERLIO_F_WRBUF) && (e->base.ptr > e->base.buf)) {
+           if (e->inEncodeCall) return 0;
            /* Write case - encode the buffer and write() to layer below */
            PUSHSTACKi(PERLSI_MAGIC);
            SPAGAIN;
@@ -416,9 +419,12 @@ PerlIOEncode_flush(pTHX_ PerlIO * f)
            XPUSHs(e->bufsv);
            XPUSHs(e->chk);
            PUTBACK;
+           e->inEncodeCall = 1;
            if (call_method("encode", G_SCALAR) != 1) {
+               e->inEncodeCall = 0;
                Perl_die(aTHX_ "panic: encode did not return a value");
            }
+           e->inEncodeCall = 0;
            SPAGAIN;
            str = POPs;
            PUTBACK;
@@ -453,6 +459,7 @@ PerlIOEncode_flush(pTHX_ PerlIO * f)
            }
            /* See if there is anything left in the buffer */
            if (e->base.ptr < e->base.end) {
+               if (e->inEncodeCall) return 0;
                /* Bother - have unread data.
                   re-encode and unread() to layer below
                 */
@@ -472,9 +479,12 @@ PerlIOEncode_flush(pTHX_ PerlIO * f)
                XPUSHs(str);
                XPUSHs(e->chk);
                PUTBACK;
+               e->inEncodeCall = 1;
                if (call_method("encode", G_SCALAR) != 1) {
-                    Perl_die(aTHX_ "panic: encode did not return a value");
+                   e->inEncodeCall = 0;
+                   Perl_die(aTHX_ "panic: encode did not return a value");
                }
+               e->inEncodeCall = 0;
                SPAGAIN;
                str = POPs;
                PUTBACK;
diff --git a/ext/PerlIO/encoding/t/nolooping.t b/ext/PerlIO/encoding/t/nolooping.t
new file mode 100644 (file)
index 0000000..9ed1e44
--- /dev/null
@@ -0,0 +1,9 @@
+#!perl -w
+
+use Test::More tests => 1;
+
+# bug #41442
+use open ':locale';
+if (-e '/dev/null') { open STDERR, '>', '/dev/null' }
+warn "# \x{201e}\n"; # &bdquo;
+ok(1); # we got that far