Subject: | [Patch] Stash crashes when passed objects that overload cmp in way that can die |
If you use the Perl version of Stash and pass in an object that
overloads the cmp operator, and that overloaded operator happens to die
during the compare that happens in line 685 of Stash.pm (the _dotop
method), then Stash will crash.
A prime example of this is the DateTime module. It croaks if you try to
compare a DateTime object to something that isn't a DateTime object.
I have attached a patch that fixes the problem and adds some tests to
stash.t and stash-xs.t to make sure it doesn't happen again.
The problem doesn't appear to occur in the XS version of Stash, but I
went ahead and put the tests into stash-xs.t anyway, just to be sure.
Thanks for your work on this great module!
Curtis H.
Subject: | FixOverloadProblem.patch |
Index: lib/Template/Stash.pm
===================================================================
RCS file: /template-toolkit/Template2/lib/Template/Stash.pm,v
retrieving revision 2.105
diff -r2.105 Stash.pm
28a29
> use Scalar::Util 'refaddr';
386c387,391
< my $atroot = ($root eq $self);
---
>
> # Note that we need to compare the reference addresses instead of the
> # references themselves because $self could be an object that overrides
> # the comparison operators.
> my $atroot = (ref $self eq ref $root) && (refaddr($root) == refaddr($self));
Index: t/stash-xs.t
===================================================================
RCS file: /template-toolkit/Template2/t/stash-xs.t,v
retrieving revision 2.12
diff -r2.12 stash-xs.t
61a62,74
> package CmpOverloadObject;
>
> use overload ('cmp' => 'compare_overload', '<=>', 'compare_overload');
>
> sub new { bless {}, shift };
>
> sub hello {
> return "Hello";
> }
>
> sub compare_overload {
> die "Mayhem!";
> }
89a103
> compareoverloaded => CmpOverloadObject->new(),
345a360,366
>
> # Exercise the object with the funky overloaded comparison
>
> -- test --
> [% compareoverloaded.hello %]
> -- expect --
> Hello
Index: t/stash.t
===================================================================
RCS file: /template-toolkit/Template2/t/stash.t,v
retrieving revision 2.18
diff -r2.18 stash.t
48a49,62
> package CmpOverloadObject;
>
> use overload ('cmp' => 'compare_overload', '<=>', 'compare_overload');
>
> sub new { bless {}, shift };
>
> sub hello {
> return "Hello";
> }
>
> sub compare_overload {
> die "Mayhem!";
> }
>
75a90
> compareoverloaded => CmpOverloadObject->new(),
278a294,301
>
> # Exercise the object with the funky overloaded comparison
>
> -- test --
> [% compareoverloaded.hello %]
> -- expect --
> Hello
>