]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix "*" in SEARCH seqset/uidset
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 15 Dec 2016 13:20:02 +0000 (15:20 +0200)
committerGitLab <gitlab@git.dovecot.net>
Thu, 15 Dec 2016 14:14:48 +0000 (16:14 +0200)
4294967295 is used for "*", which matches the last existing message.
Which we don't know what it is at the time of search args simplification,
so avoid making any assumptions about it.

It's a bit ugly that 4294967295 can't be used as a valid UID, but this
restriction has already existed since the beginning of Dovecot. A future
alternative might be to add MAIL_SEARCH_ARG_FLAG_SEQSET_WITH_STAR, but
that's a bit complicated change.

src/lib-storage/mail-search-args-simplify.c
src/lib-storage/test-mail-search-args-simplify.c

index 3a6601ff5cf673811ea2de943f2b32619223b70e..d596e5341abaff7364dcff6014ebcd05193c1389 100644 (file)
@@ -112,12 +112,17 @@ static void mail_search_args_simplify_set(struct mail_search_arg *args)
        unsigned int count;
 
        if (args->match_not) {
-               /* invert the set to drop the NOT */
+               /* invert the set to drop the NOT. Note that (uint32_t)-1
+                  matches the last existing mail, which we don't know at this
+                  point. lib-imap/imap-seqset.c has similar code that
+                  disallows using (uint32_t)-1 as a real UID. */
+               if (seq_range_exists(&args->value.seqset, (uint32_t)-1))
+                       return;
                args->match_not = FALSE;
-               seq_range_array_invert(&args->value.seqset, 1, (uint32_t)-1);
+               seq_range_array_invert(&args->value.seqset, 1, (uint32_t)-2);
        }
        seqset = array_get(&args->value.seqset, &count);
-       if (count == 1 && seqset->seq1 == 1 && seqset->seq2 == (uint32_t)-1) {
+       if (count == 1 && seqset->seq1 == 1 && seqset->seq2 >= (uint32_t)-2) {
                /* 1:* is the same as ALL. */
                args->type = SEARCH_ALL;
        } else if (count == 0) {
@@ -134,7 +139,10 @@ static bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
        struct mail_search_simplify_prev_arg mask;
        struct mail_search_arg **prev_argp;
 
-       i_assert(!args->match_not);
+       if (args->match_not) {
+               /* "*" used - can't simplify it */
+               return FALSE;
+       }
 
        mail_search_arg_get_base_mask(args, &mask);
        prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
index e17629e79f5aedc6ca95bb6b32d94bcc5f48994e..e3cb422da2e1a3b4da182b797ea8880ac367bb81 100644 (file)
@@ -49,27 +49,34 @@ struct {
        { "1:* 1:*", "ALL" },
        { "OR 1:5 6:*", "ALL" },
 
+       { "UID 1:* UID 1:*", "ALL" },
+       { "OR UID 1:5 UID 6:*", "ALL" },
+
        { "2:* 2:*", "2:4294967295" },
        { "OR 2:* 2:*", "2:4294967295" },
 
+       { "UID 2:* UID 2:*", "UID 2:4294967295" },
+       { "OR UID 2:* UID 2:*", "UID 2:4294967295" },
+
        { "1:5 6:7", "NOT ALL" },
        { "1:5 3:7", "3:5" },
        { "1:5 3:7 4:9", "4:5" },
        { "1:5 OR 3:4 4:6", "3:5" },
        { "OR 1 2", "1:2" },
-       { "NOT 1,3:5", "2,6:4294967295" },
-       { "NOT 1:100 NOT 50:200", "201:4294967295" },
-       { "OR NOT 1:100 NOT 50:200", "1:49,101:4294967295" },
+       { "NOT 1,3:5", "2,6:4294967294" },
+       { "NOT 1:100 NOT 50:200", "201:4294967294" },
+       { "OR NOT 1:100 NOT 50:200", "1:49,101:4294967294" },
 
        { "UID 1:5 UID 6:7", "NOT ALL" },
        { "UID 1:5 UID 3:7", "UID 3:5" },
        { "OR UID 1 UID 2", "UID 1:2" },
-       { "NOT UID 1,3:5", "UID 2,6:4294967295" },
+       { "NOT UID 1,3:5", "UID 2,6:4294967294" },
 
        { "1:5 UID 10:20", "1:5 UID 10:20" },
-       { "1:5 NOT UID 10:20", "1:5 UID 1:9,21:4294967295" },
+       { "1:5 NOT UID 10:20", "1:5 UID 1:9,21:4294967294" },
 
-       { "ALL NOT UID 3:*", "UID 1:2" },
+       { "ALL NOT UID 3:*", "NOT UID 3:4294967295" },
+       { "NOT 1:10 NOT *", "11:4294967294 NOT 4294967295" },
 
        { "BEFORE 03-Aug-2014 BEFORE 01-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"01-Aug-2014\"" },
        { "OR BEFORE 01-Aug-2014 BEFORE 02-Aug-2014", "BEFORE \"02-Aug-2014\"" },