I've already tracked this down, fixed it, and submitted a patch to the author. But I thought this could be a fun practice problem for other people to look at.

On Perl 5.8 (I haven't tried it in 5.10), the following script segfaults:

#! /usr/bin/perl use strict; use warnings; use Template; my $template = Template->new({}); my $text = "[% SET content='" . ("stuff "x20_000) . "' %]"; $template->process(\$text, {}); print "Processed\n";
What Perl bug is this tripping over? How could Template Toolkit be fixed to not trigger the segfault?

Replies are listed 'Best First'.
Re: Challenge, try to fix the bug
by fullermd (Vicar) on Oct 16, 2009 at 07:16 UTC

    Actually, as fate would have it, it doesn't segfault for me :). It does give a warning during the run, however; that may hint in the right direction.

    This is perl, v5.8.9 built for amd64-freebsd

      Ah. It segfaults for me on 5.8.8. And yes, the warning likely does give a useful hint.
Re: Challenge, try to fix the bug
by JavaFan (Canon) on Oct 16, 2009 at 08:51 UTC
    In 5.10, it won't segfault. It will warn though, but the bug is (partially) fixed, and as far as I can tell, it's working in this case.
Re: Challenge, try to fix the bug
by Tanktalus (Canon) on Oct 20, 2009 at 22:21 UTC

    I'm having a hard time with it. I've narrowed down, I think, the crash to this regex in Template::Parser:

    while ($text =~ s/ ^(.*?) # $1 - start of line up to directive (?: $start # start of tag (.*?) # $2 - tag contents $end # end of tag ) //sx) {
    But what's odd is that if I eliminate all of Template Toolkit, and just use that while loop in my main script, no seg fault. What's even more curious is that if I leave that while in there and then run process, then there's still no segfault. I thought that maybe it's leaving the \G marker or something around, but even assigning to pos($text) doesn't reintroduce the segfault.
    #!/usr/bin/perl use strict; use warnings; use Template; #use Template::Parser; my $template = Template->new({}); my $text = "[% SET content='" . ("stuff "x20_000) . "' %]"; my $start = qr/\Q[%/; my $end = qr/\Q%]/; while ($text =~ s/ ^(.*?) # $1 - start of line up to directive (?: $start # start of tag (.*?) # $2 - tag contents $end # end of tag ) //sx) { #print "1=$1\n2=$2\n"; } pos($text) = 0; $template->process(\$text, {}); print "Processed\n";
    This script works (rather, it doesn't segfault), and leaves me more confused than when I started.

    (Perl 5.8.8 here)

      You have the right idea and module, but the wrong regular expression.

      I started by creating a local copy of Template that I could add debugging statements to. Using a binary search I found the last function call within process it executed, then went to that function and found where it died there, and before long found the actual place where it dies.