changeset 21310:8860c79510c5

lib-storage: Fix "*" in SEARCH seqset/uidset 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.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 15 Dec 2016 15:20:02 +0200
parents d9493cd93820
children 04ba3511d02a
files src/lib-storage/mail-search-args-simplify.c src/lib-storage/test-mail-search-args-simplify.c
diffstat 2 files changed, 25 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/mail-search-args-simplify.c	Thu Dec 15 15:01:47 2016 +0200
+++ b/src/lib-storage/mail-search-args-simplify.c	Thu Dec 15 15:20:02 2016 +0200
@@ -112,12 +112,17 @@
 	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 @@
 	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);
--- a/src/lib-storage/test-mail-search-args-simplify.c	Thu Dec 15 15:01:47 2016 +0200
+++ b/src/lib-storage/test-mail-search-args-simplify.c	Thu Dec 15 15:20:02 2016 +0200
@@ -49,27 +49,34 @@
 	{ "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\"" },