From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id B64C01F957 for ; Sun, 5 Jul 2020 23:28:15 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 41/43] gzipfilter: drop HTTP connection on bugs or data corruption Date: Sun, 5 Jul 2020 23:27:57 +0000 Message-Id: <20200705232759.3161-42-e@yhbt.net> In-Reply-To: <20200705232759.3161-1-e@yhbt.net> References: <20200705232759.3161-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: While all the {async_next} callbacks needed eval guards anyways because of DS->write, {async_eml} callbacks did not. Ensure any bugs in our code or data corruption result in termination of the HTTP connection, so as not to leave clients hanging on a response which never comes or is mangled in some way. --- lib/PublicInbox/GzipFilter.pm | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/PublicInbox/GzipFilter.pm b/lib/PublicInbox/GzipFilter.pm index d72ad3c88..57344604b 100644 --- a/lib/PublicInbox/GzipFilter.pm +++ b/lib/PublicInbox/GzipFilter.pm @@ -147,18 +147,34 @@ sub close { } } +sub bail { + my $self = shift; + if (my $env = $self->{env}) { + eval { $env->{'psgi.errors'}->print(@_, "\n") }; + warn("E: error printing to psgi.errors: $@", @_) if $@; + my $http = $env->{'psgix.io'} or return; # client abort + eval { $http->close }; # should hit our close + warn "E: error in http->close: $@" if $@; + eval { $self->close }; # just in case... + warn "E: error in self->close: $@" if $@; + } else { + warn @_, "\n"; + } +} + # this is public-inbox-httpd-specific sub async_blob_cb { # git->cat_async callback my ($bref, $oid, $type, $size, $self) = @_; my $http = $self->{env}->{'psgix.io'} or return; # client abort - my $smsg = $self->{smsg} or die 'BUG: no smsg'; + my $smsg = $self->{smsg} or bail($self, 'BUG: no smsg'); if (!defined($oid)) { # it's possible to have TOCTOU if an admin runs # public-inbox-(edit|purge), just move onto the next message return $http->next_step($self->{async_next}); } - $smsg->{blob} eq $oid or die "BUG: $smsg->{blob} != $oid"; - $self->{async_eml}->($self, PublicInbox::Eml->new($bref)); + $smsg->{blob} eq $oid or bail($self, "BUG: $smsg->{blob} != $oid"); + eval { $self->{async_eml}->($self, PublicInbox::Eml->new($bref)) }; + bail($self, "E: async_eml: $@") if $@; $http->next_step($self->{async_next}); }