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 527751FBEB for ; Wed, 10 Jun 2020 07:06:26 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 38/82] imap: support out-of-bounds ranges Date: Wed, 10 Jun 2020 07:04:35 +0000 Message-Id: <20200610070519.18252-39-e@yhbt.net> In-Reply-To: <20200610070519.18252-1-e@yhbt.net> References: <20200610070519.18252-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: "$UID_START:*" needs to return at least one message according to RFC 3501 section 6.4.8. While we're in the area, coerce ranges to (unsigned) integers by adding zero ("+ 0") to reduce memory overhead. --- lib/PublicInbox/IMAP.pm | 8 +++++--- t/imapd.t | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm index 3815141a15e..ffa76bb0266 100644 --- a/lib/PublicInbox/IMAP.pm +++ b/lib/PublicInbox/IMAP.pm @@ -455,11 +455,13 @@ sub range_step ($$) { $$range_csv = undef; } if ($range =~ /\A([0-9]+):([0-9]+)\z/) { - ($beg, $end) = ($1, $2); + ($beg, $end) = ($1 + 0, $2 + 0); } elsif ($range =~ /\A([0-9]+):\*\z/) { - ($beg, $end) = ($1, $ibx->mm->max // 0); + $beg = $1 + 0; + $end = $ibx->mm->max // 0; + $beg = $end if $beg > $end; } elsif ($range =~ /\A[0-9]+\z/) { - $beg = $end = $range; + $beg = $end = $range + 0; } else { return 'BAD fetch range'; } diff --git a/t/imapd.t b/t/imapd.t index 3d0be340846..2c4315dec30 100644 --- a/t/imapd.t +++ b/t/imapd.t @@ -116,6 +116,19 @@ $ret = $mic->search('uid 1:*') or BAIL_OUT "SEARCH FAIL $@"; is_deeply($ret, [ 1 ], 'search UID 1:* works'); is_deeply(scalar $mic->flags('1'), [], '->flags works'); +{ + # RFC 3501 section 6.4.8 states: + # Also note that a UID range of 559:* always includes the + # UID of the last message in the mailbox, even if 559 is + # higher than any assigned UID value. + my $exp = $mic->fetch_hash(1, 'UID'); + $ret = $mic->fetch_hash('559:*', 'UID'); + is_deeply($ret, $exp, 'beginning range too big'); + for my $r (qw(559:558 558:559)) { + $ret = $mic->fetch_hash($r, 'UID'); + is_deeply($ret, {}, "out-of-range UID FETCH $r"); + } +} for my $r ('1:*', '1') { $ret = $mic->fetch_hash($r, 'RFC822') or BAIL_OUT "FETCH $@";