There is a problem when handling bogus serialized MessagePack data.
$unpacker->execute is not protected by an eval. So when an exception
occurs in Data::MessagePack, the program dies (except with EV that
catches it) instead of calling the on_error callback.
The attached patch corrects this behavior.
The attached test allows to validate it.
Best regards,
Max.
Subject: | 01_handle_error.t |
use strict;
use warnings;
BEGIN {
# To avoid EV that catches exceptions...
$ENV{PERL_ANYEVENT_MODEL} = 'Perl';
}
use AE;
use AnyEvent::MessagePack;
use AnyEvent::Handle; # will load Errno for us
use File::Temp qw(tempfile);
use Test::More tests => 1;
my ($fh, $fname) = tempfile(UNLINK => 0);
my $cv = AE::cv;
{
my $hdl = AnyEvent::Handle->new(fh => $fh, on_error => sub { die 'wtf' });
$hdl->push_write("\xc1");
close $fh;
}
my $hdl = do {
open my $fh, '<', $fname or die $!;
my $hdl = AnyEvent::Handle->new(fh => $fh,
on_error => sub { $cv->send($_[2]) });
$hdl->push_read(msgpack => sub {
$cv->send(0);
});
$hdl;
};
is($cv->recv(), do { local $! = Errno::EBADMSG; "$!" });
unlink $fname;
Subject: | AnyEvent-MessagePack.patch |
--- lib/AnyEvent/MessagePack.pm.orig 2011-11-20 23:30:36.000000000 +0100
+++ lib/AnyEvent/MessagePack.pm 2012-03-20 11:46:27.000000000 +0100
@@ -23,7 +23,10 @@
my $complete = 0;
my $nread = 0;
while(1) {
- $nread = $unpacker->execute($buffer, $nread);
+ unless (eval { $nread = $unpacker->execute($buffer, $nread); 1 }) {
+ $self->_error(Errno::EBADMSG);
+ return;
+ }
if ($unpacker->is_finished) {
my $ret = $unpacker->data;
$cb->( $_[0], $ret );