[Rt-commit] rt branch, 3.8/gnupg-decrypt-verify-deadlock, created. rt-3.8.15-3-g990db0e

Alex Vandiver alexmv at bestpractical.com
Wed Dec 12 19:11:35 EST 2012


The branch, 3.8/gnupg-decrypt-verify-deadlock has been created
        at  990db0edc4d4fae7eb09c854e854bd1a96882855 (commit)

- Log -----------------------------------------------------------------
commit 57a232996cada06c78074602b43c741ea92b7c69
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Dec 13 01:07:27 2012 +0400

    stop RT from locking on "large" mails
    
    Recent improvement in search for GnuPG encrypted/signed parts
    introduced a deadlock situation. Happens on mail delivery with
    GnuPG enabled and the mail containing a "large" quoted printable
    or base64 encoded part. Size depends on OS and system
    configuration. Symptoms: web server process hangs doing nothing,
    rt-mailgate times out, no messages in logs.
    
    It is incorrect use of pipe inside one process. After some ammount
    of data, Writer just blocks waiting for reader to fetch it.
    
    The commit in question is 258ec2fb531c83df00afae3f428975b9871e1f68
    that was included into 3.8.15 and 4.0.8rc1.

diff --git a/lib/RT/Crypt/GnuPG.pm b/lib/RT/Crypt/GnuPG.pm
index f8931b6..045327c 100644
--- a/lib/RT/Crypt/GnuPG.pm
+++ b/lib/RT/Crypt/GnuPG.pm
@@ -905,11 +905,23 @@ sub FindProtectedParts {
         # sense) unnecessarily applies a base64 transfer encoding to PGP
         # mail (whose content is already base64-encoded).
         if ( $entity->bodyhandle->is_encoded and $entity->head->mime_encoding ) {
-            pipe( my ($read_decoded, $write_decoded) );
             my $decoder = MIME::Decoder->new( $entity->head->mime_encoding );
             if ($decoder) {
-                eval { $decoder->decode($io, $write_decoded) };
-                $io = $read_decoded;
+                local $@;
+                eval {
+                    my $buf = '';
+                    open my $fh, '>:raw', \$buf
+                        or die "Couldn't open scalar for writing: $!";
+                    $decoder->decode($io, $fh);
+                    close $fh or die "Couldn't close scalar: $!";
+
+                    open $fh, '<:raw', \$buf
+                        or die "Couldn't re-open scalar for reading: $!";
+                    $io = $fh;
+                    1;
+                } or do {
+                    $RT::Logger->error("Couldn't decode body: $@");
+                }
             }
         }
 
diff --git a/t/mail/gnupg-incoming.t b/t/mail/gnupg-incoming.t
index c34ed99..2ec2fc2 100644
--- a/t/mail/gnupg-incoming.t
+++ b/t/mail/gnupg-incoming.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 47;
+use RT::Test tests => 50;
 
 plan skip_all => 'GnuPG required.'
     unless eval 'use GnuPG::Interface; 1';
@@ -243,7 +243,6 @@ RT::Test->close_mailgate_ok($mail);
     ok(index($orig->Content, $buf) != -1, 'found original msg');
 }
 
-
 # test for signed mail by other key
 $buf = '';
 
@@ -355,3 +354,29 @@ is(@mail, 1, 'caught outgoing mail.');
     unlike( ($attach ? $attach->Content : ''), qr'really should not be there either');
 }
 
+
+# test that if it gets base64 transfer-encoded long mail then it doesn't hang
+{
+    local $SIG{ALRM} = sub {
+        ok 0, "timed out, web server is probably in deadlock";
+        exit;
+    };
+    alarm 30;
+    $buf = encode_base64('a'x(250*1024));
+    $mail = RT::Test->open_mailgate_ok($baseurl);
+    print $mail <<"EOF";
+From: recipient\@example.com
+To: general\@$RT::rtname
+Content-transfer-encoding: base64
+Subject: Long not encrypted message for queue
+
+$buf
+EOF
+    RT::Test->close_mailgate_ok($mail);
+    alarm 0;
+
+    my $tick = RT::Test->last_ticket;
+    is( $tick->Subject, 'Long not encrypted message for queue',
+        "Created the ticket"
+    );
+}

commit 990db0edc4d4fae7eb09c854e854bd1a96882855
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Dec 13 01:58:17 2012 +0400

    make sure data is recorded (tests)

diff --git a/t/mail/gnupg-incoming.t b/t/mail/gnupg-incoming.t
index 2ec2fc2..c87925a 100644
--- a/t/mail/gnupg-incoming.t
+++ b/t/mail/gnupg-incoming.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 50;
+use RT::Test tests => 51;
 
 plan skip_all => 'GnuPG required.'
     unless eval 'use GnuPG::Interface; 1';
@@ -379,4 +379,6 @@ EOF
     is( $tick->Subject, 'Long not encrypted message for queue',
         "Created the ticket"
     );
+    my $content = $tick->Transactions->First->Content;
+    like $content, qr/a{1024,}/, 'content is not lost';
 }

-----------------------------------------------------------------------


More information about the Rt-commit mailing list