"$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 $@";
--
unsubscribe: one-click, see List-Unsubscribe header
archive: https://public-inbox.org/meta/

Reply via email to