Fix the "UNIX mailbox first message symptom".
UFMS, or "UNIX mailbox first message symptom", is a long-standing bug that existed in all previous versions of Mailutils: under certain circumstances, a fragment of the message headers would get prepended to the body of the very first message in a UNIX mailbox. See the detailed description in testsuite/ufms.c. Along with fixing this bug, this change also ensures a proper restoring of UIDs from UNIX mailboxes. * libproto/mbox/mbox.c (_msg_body_setup): Call mu_body_clear_modified after constructing the body. (new_message): Ditto for mu_message_clear_modified. (mbox_reset): Rewrite. Drop all cached messages and rescan entire mailbox to avoid the "1st message symptom". (mbox_expunge0): Change the call to mbox_reset. * libproto/mbox/mboxscan.c (IS_X_UID, IS_X_IMAPBASE): New macros. (mbox_scan_internal): Change handling of min_uid. Attempt to get UID and imapbase from the corresponding message headers. (mbox_scan0): Reflect the above changes. * testsuite/.gitignore: Add ufms. * testsuite/Makefile.am (noinst_PROGRAMS): Add ufms. (TESTSUITE_AT): Add ufms.at. * testsuite/testsuite.at: Include ufms.at. * testsuite/ufms.at: New test case. * testsuite/ufms.c: New test program. * imap4d/testsuite/imap4d/expunge.exp: Fix UIDNEXT expectation.
Showing
8 changed files
with
242 additions
and
33 deletions
... | @@ -63,7 +63,7 @@ imap4d_test "SELECT mbox1" \ | ... | @@ -63,7 +63,7 @@ imap4d_test "SELECT mbox1" \ |
63 | "1 EXISTS"\ | 63 | "1 EXISTS"\ |
64 | "0 RECENT"\ | 64 | "0 RECENT"\ |
65 | -re {OK \[UIDVALIDITY [0-9]+\] UID valididy status}\ | 65 | -re {OK \[UIDVALIDITY [0-9]+\] UID valididy status}\ |
66 | "OK \[UIDNEXT 2\] Predicted next uid"\ | 66 | "OK \[UIDNEXT 6\] Predicted next uid"\ |
67 | "OK \[UNSEEN 1\] first unseen messsage"\ | 67 | "OK \[UNSEEN 1\] first unseen messsage"\ |
68 | "FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)"\ | 68 | "FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)"\ |
69 | "OK \[PERMANENTFLAGS (\\Answered \\Deleted \\Seen)\] Permanent flags" \ | 69 | "OK \[PERMANENTFLAGS (\\Answered \\Deleted \\Seen)\] Permanent flags" \ | ... | ... |
... | @@ -349,6 +349,7 @@ _msg_body_setup (mu_message_t msg, mbox_message_t mum) | ... | @@ -349,6 +349,7 @@ _msg_body_setup (mu_message_t msg, mbox_message_t mum) |
349 | mu_body_set_stream (body, stream, msg); | 349 | mu_body_set_stream (body, stream, msg); |
350 | mu_body_set_size (body, mbox_body_size, msg); | 350 | mu_body_set_size (body, mbox_body_size, msg); |
351 | mu_body_set_lines (body, mbox_body_lines, msg); | 351 | mu_body_set_lines (body, mbox_body_lines, msg); |
352 | mu_body_clear_modified (body); | ||
352 | mu_message_set_body (msg, body, mum); | 353 | mu_message_set_body (msg, body, mum); |
353 | } | 354 | } |
354 | return status; | 355 | return status; |
... | @@ -571,6 +572,8 @@ new_message (mu_mailbox_t mailbox, mbox_message_t mum, mu_message_t *pmsg) | ... | @@ -571,6 +572,8 @@ new_message (mu_mailbox_t mailbox, mbox_message_t mum, mu_message_t *pmsg) |
571 | mum->message = msg; | 572 | mum->message = msg; |
572 | mu_message_set_mailbox (msg, mailbox, mum); | 573 | mu_message_set_mailbox (msg, mailbox, mum); |
573 | 574 | ||
575 | mu_message_clear_modified (msg); | ||
576 | |||
574 | *pmsg = msg; | 577 | *pmsg = msg; |
575 | 578 | ||
576 | return 0; | 579 | return 0; |
... | @@ -1149,37 +1152,18 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) | ... | @@ -1149,37 +1152,18 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) |
1149 | 1152 | ||
1150 | 1153 | ||
1151 | static void | 1154 | static void |
1152 | mbox_reset (mu_mailbox_t mailbox, size_t dirty, int remove_deleted) | 1155 | mbox_reset (mu_mailbox_t mailbox) |
1153 | { | 1156 | { |
1154 | mbox_data_t mud = mailbox->data; | 1157 | mbox_data_t mud = mailbox->data; |
1155 | size_t i; | 1158 | size_t i; |
1156 | size_t dlast; | ||
1157 | 1159 | ||
1158 | mu_monitor_wrlock (mailbox->monitor); | 1160 | mu_monitor_wrlock (mailbox->monitor); |
1159 | for (i = dirty, dlast = mud->messages_count - 1; i <= dlast; i++) | 1161 | for (i = 0; i < mud->messages_count; i++) |
1160 | { | 1162 | { |
1161 | /* Clear all the references */ | 1163 | /* Clear all the references */ |
1162 | mbox_message_t mum = mud->umessages[i]; | 1164 | mbox_message_t mum = mud->umessages[i]; |
1163 | if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags)) | 1165 | mu_message_destroy (&mum->message, mum); |
1164 | { | ||
1165 | if ((i + 1) <= dlast) | ||
1166 | { | ||
1167 | /* Move all the pointers up. So the message pointer | ||
1168 | part of mum will be at the right position. */ | ||
1169 | memmove (mud->umessages + i, mud->umessages + i + 1, | ||
1170 | (dlast - i) * sizeof (mum)); | ||
1171 | memset (mum, 0, sizeof (*mum)); | ||
1172 | /* We are not free()ing the useless mum, but instead | ||
1173 | we put it back in the pool, to be reused. */ | ||
1174 | mud->umessages[dlast] = mum; | ||
1175 | dlast--; | ||
1176 | /* Set mum to the new value after the memmove so it | ||
1177 | gets cleared to. */ | ||
1178 | mum = mud->umessages[i]; | ||
1179 | } | ||
1180 | else | ||
1181 | memset (mum, 0, sizeof (*mum)); | 1166 | memset (mum, 0, sizeof (*mum)); |
1182 | } | ||
1183 | mum->envel_from = mum->envel_from_end = 0; | 1167 | mum->envel_from = mum->envel_from_end = 0; |
1184 | mum->body = mum->body_end = 0; | 1168 | mum->body = mum->body_end = 0; |
1185 | mum->header_lines = mum->body_lines = 0; | 1169 | mum->header_lines = mum->body_lines = 0; |
... | @@ -1187,7 +1171,7 @@ mbox_reset (mu_mailbox_t mailbox, size_t dirty, int remove_deleted) | ... | @@ -1187,7 +1171,7 @@ mbox_reset (mu_mailbox_t mailbox, size_t dirty, int remove_deleted) |
1187 | mu_monitor_unlock (mailbox->monitor); | 1171 | mu_monitor_unlock (mailbox->monitor); |
1188 | /* This resets the messages_count, the last argument 0 means | 1172 | /* This resets the messages_count, the last argument 0 means |
1189 | not to send event notification. */ | 1173 | not to send event notification. */ |
1190 | mbox_scan0 (mailbox, dirty, NULL, 0); | 1174 | mbox_scan0 (mailbox, 1, NULL, 0); |
1191 | } | 1175 | } |
1192 | 1176 | ||
1193 | static int | 1177 | static int |
... | @@ -1434,7 +1418,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) | ... | @@ -1434,7 +1418,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) |
1434 | mu_stream_destroy (&tempstr); | 1418 | mu_stream_destroy (&tempstr); |
1435 | 1419 | ||
1436 | if (status == 0) | 1420 | if (status == 0) |
1437 | mbox_reset (mailbox, dirty, remove_deleted); | 1421 | mbox_reset (mailbox); |
1438 | } | 1422 | } |
1439 | if (mailbox->locker) | 1423 | if (mailbox->locker) |
1440 | mu_locker_unlock (mailbox->locker); | 1424 | mu_locker_unlock (mailbox->locker); | ... | ... |
... | @@ -34,6 +34,8 @@ | ... | @@ -34,6 +34,8 @@ |
34 | 34 | ||
35 | #include <stdlib.h> | 35 | #include <stdlib.h> |
36 | #include <mbox0.h> | 36 | #include <mbox0.h> |
37 | #include <mailutils/cctype.h> | ||
38 | #include <mailutils/cstr.h> | ||
37 | 39 | ||
38 | /* Parsing. | 40 | /* Parsing. |
39 | The approach is to detect the "From " as start of a new message, give the | 41 | The approach is to detect the "From " as start of a new message, give the |
... | @@ -279,6 +281,26 @@ do \ | ... | @@ -279,6 +281,26 @@ do \ |
279 | && (buf[5] == 'S' || buf[5] == 's') \ | 281 | && (buf[5] == 'S' || buf[5] == 's') \ |
280 | && (buf[6] == ':' || buf[6] == ' ' || buf[6] == '\t')) | 282 | && (buf[6] == ':' || buf[6] == ' ' || buf[6] == '\t')) |
281 | 283 | ||
284 | #define IS_X_UID(buf) ( \ | ||
285 | (buf[0] == 'X' || buf[0] == 'x') \ | ||
286 | && buf[1] == '-' \ | ||
287 | && (buf[2] == 'U' || buf[2] == 'u') \ | ||
288 | && (buf[3] == 'I' || buf[3] == 'i') \ | ||
289 | && (buf[4] == 'D' || buf[4] == 'd') \ | ||
290 | && (buf[5] == ':' || buf[5] == ' ' || buf[5] == '\t')) | ||
291 | #define IS_X_IMAPBASE(buf) ( \ | ||
292 | (buf[0] == 'X' || buf[0] == 'x') \ | ||
293 | && buf[1] == '-' \ | ||
294 | && (buf[2] == 'I' || buf[2] == 'i') \ | ||
295 | && (buf[3] == 'M' || buf[3] == 'm') \ | ||
296 | && (buf[4] == 'A' || buf[4] == 'a') \ | ||
297 | && (buf[5] == 'P' || buf[5] == 'p') \ | ||
298 | && (buf[6] == 'B' || buf[6] == 'b') \ | ||
299 | && (buf[7] == 'A' || buf[7] == 'a') \ | ||
300 | && (buf[8] == 'S' || buf[8] == 's') \ | ||
301 | && (buf[9] == 'E' || buf[9] == 'e') \ | ||
302 | && (buf[10] == ':' || buf[10] == ' ' || buf[10] == '\t')) | ||
303 | |||
282 | #define MBOX_SCAN_NOTIFY 0x1 | 304 | #define MBOX_SCAN_NOTIFY 0x1 |
283 | #define MBOX_SCAN_ONEMSG 0x2 | 305 | #define MBOX_SCAN_ONEMSG 0x2 |
284 | 306 | ||
... | @@ -298,7 +320,7 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, | ... | @@ -298,7 +320,7 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, |
298 | int newline; | 320 | int newline; |
299 | size_t n = 0; | 321 | size_t n = 0; |
300 | mu_stream_t stream; | 322 | mu_stream_t stream; |
301 | size_t min_uid = 0; | 323 | size_t min_uid = 1; |
302 | int zn, isfrom = 0; | 324 | int zn, isfrom = 0; |
303 | char *temp; | 325 | char *temp; |
304 | 326 | ||
... | @@ -345,9 +367,9 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, | ... | @@ -345,9 +367,9 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, |
345 | mum->body_end = total - n - newline; | 367 | mum->body_end = total - n - newline; |
346 | mum->body_lines = --lines - newline; | 368 | mum->body_lines = --lines - newline; |
347 | 369 | ||
348 | if (mum->uid <= min_uid) | 370 | if (mum->uid < min_uid) |
349 | { | 371 | { |
350 | mum->uid = ++min_uid; | 372 | mum->uid = min_uid++; |
351 | /* Note that modification for when expunging. */ | 373 | /* Note that modification for when expunging. */ |
352 | mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; | 374 | mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; |
353 | } | 375 | } |
... | @@ -370,13 +392,32 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, | ... | @@ -370,13 +392,32 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, |
370 | mum->attr_flags = 0; | 392 | mum->attr_flags = 0; |
371 | lines = 0; | 393 | lines = 0; |
372 | } | 394 | } |
373 | else if (ISSTATUS(buf)) | 395 | else if (ISSTATUS (buf)) |
374 | { | 396 | { |
375 | ATTRIBUTE_SET(buf, mum, 'r', 'R', MU_ATTRIBUTE_READ); | 397 | ATTRIBUTE_SET(buf, mum, 'r', 'R', MU_ATTRIBUTE_READ); |
376 | ATTRIBUTE_SET(buf, mum, 'o', 'O', MU_ATTRIBUTE_SEEN); | 398 | ATTRIBUTE_SET(buf, mum, 'o', 'O', MU_ATTRIBUTE_SEEN); |
377 | ATTRIBUTE_SET(buf, mum, 'a', 'A', MU_ATTRIBUTE_ANSWERED); | 399 | ATTRIBUTE_SET(buf, mum, 'a', 'A', MU_ATTRIBUTE_ANSWERED); |
378 | ATTRIBUTE_SET(buf, mum, 'd', 'D', MU_ATTRIBUTE_DELETED); | 400 | ATTRIBUTE_SET(buf, mum, 'd', 'D', MU_ATTRIBUTE_DELETED); |
379 | } | 401 | } |
402 | else if (IS_X_UID (buf)) | ||
403 | { | ||
404 | char *p; | ||
405 | unsigned long n = strtoul (buf + 6, &p, 10); | ||
406 | if (*p == 0 || mu_isspace (*p)) | ||
407 | mum->uid = min_uid = n; | ||
408 | } | ||
409 | else if (mud->messages_count == 1 && IS_X_IMAPBASE (buf)) | ||
410 | { | ||
411 | char *p; | ||
412 | unsigned long n = strtoul (buf + 11, &p, 10); | ||
413 | if (mu_isspace (*p)) | ||
414 | mud->uidvalidity = n; | ||
415 | n = strtoul (mu_str_skip_cset (p, " \t"), &p, 10); | ||
416 | if (*p == 0 || mu_isspace (*p)) | ||
417 | mud->uidnext = n; | ||
418 | else | ||
419 | mud->uidvalidity = 0; | ||
420 | } | ||
380 | } | 421 | } |
381 | 422 | ||
382 | /* Body. */ | 423 | /* Body. */ |
... | @@ -410,9 +451,9 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, | ... | @@ -410,9 +451,9 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, |
410 | mum->body_end = total - newline; | 451 | mum->body_end = total - newline; |
411 | mum->body_lines = lines - newline; | 452 | mum->body_lines = lines - newline; |
412 | 453 | ||
413 | if (mum->uid <= min_uid) | 454 | if (mum->uid < min_uid) |
414 | { | 455 | { |
415 | mum->uid = ++min_uid; | 456 | mum->uid = min_uid++; |
416 | /* Note that modification for when expunging. */ | 457 | /* Note that modification for when expunging. */ |
417 | mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; | 458 | mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; |
418 | } | 459 | } |
... | @@ -498,7 +539,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -498,7 +539,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
498 | } | 539 | } |
499 | } | 540 | } |
500 | 541 | ||
501 | if (mud->messages_count > 0 && min_uid >= mud->uidnext) | 542 | if (mud->messages_count > 0 && min_uid > mud->uidnext) |
502 | { | 543 | { |
503 | mum = mud->umessages[0]; | 544 | mum = mud->umessages[0]; |
504 | mud->uidnext = min_uid + 1; | 545 | mud->uidnext = min_uid + 1; | ... | ... |
... | @@ -42,7 +42,8 @@ INCLUDES = @MU_LIB_COMMON_INCLUDES@ | ... | @@ -42,7 +42,8 @@ INCLUDES = @MU_LIB_COMMON_INCLUDES@ |
42 | noinst_PROGRAMS = \ | 42 | noinst_PROGRAMS = \ |
43 | mbdel\ | 43 | mbdel\ |
44 | mimetest\ | 44 | mimetest\ |
45 | smtpsend | 45 | smtpsend\ |
46 | ufms | ||
46 | 47 | ||
47 | LDADD = \ | 48 | LDADD = \ |
48 | ${MU_LIB_MBOX}\ | 49 | ${MU_LIB_MBOX}\ |
... | @@ -68,6 +69,7 @@ smtpsend_LDADD = \ | ... | @@ -68,6 +69,7 @@ smtpsend_LDADD = \ |
68 | TESTSUITE_AT = \ | 69 | TESTSUITE_AT = \ |
69 | mbdel.at\ | 70 | mbdel.at\ |
70 | mime.at\ | 71 | mime.at\ |
72 | ufms.at\ | ||
71 | testsuite.at | 73 | testsuite.at |
72 | 74 | ||
73 | TESTSUITE = $(srcdir)/testsuite | 75 | TESTSUITE = $(srcdir)/testsuite | ... | ... |
testsuite/ufms.at
0 → 100644
1 | # This file is part of GNU Mailutils. -*- Autotest -*- | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | # Check for "UNIX mbox 1st message symptom" bug. See the description in | ||
18 | # ufms.c, for a detailed description. | ||
19 | |||
20 | AT_SETUP([UNIX mbox 1st message symptom]) | ||
21 | AT_KEYWORDS([mailbox mbox mbox-ufms ufms]) | ||
22 | AT_CHECK([ | ||
23 | MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1) | ||
24 | ufms mbox:mbox1 || exit $? | ||
25 | sed 's/^\(X-IMAPbase\): \([[0-9][0-9]*]\) \(.*\)/\1: UIDVALIDITY \3/' mbox1 | ||
26 | ], | ||
27 | [0], | ||
28 | [From foobar@nonexistent.net Fri Dec 28 22:18:09 2001 | ||
29 | Received: (from foobar@nonexistent.net) | ||
30 | by nonexistent.net id fBSKI8N04906 | ||
31 | for bar@dontmailme.org; Fri, 28 Dec 2001 22:18:08 +0200 | ||
32 | Date: Fri, 28 Dec 2001 22:18:08 +0200 | ||
33 | From: Foo Bar <foobar@nonexistent.net> | ||
34 | Message-Id: <200112282018.fBSKI8N04906@nonexistent.net> | ||
35 | To: Bar <bar@dontmailme.org> | ||
36 | Subject: Jabberwocky | ||
37 | X-IMAPbase: UIDVALIDITY 6 | ||
38 | Status: R | ||
39 | X-UID: 1 | ||
40 | |||
41 | `Twas brillig, and the slithy toves | ||
42 | Did gyre and gimble in the wabe; | ||
43 | All mimsy were the borogoves, | ||
44 | And the mome raths outgrabe. | ||
45 | |||
46 | `Beware the Jabberwock, my son! | ||
47 | The jaws that bite, the claws that catch! | ||
48 | Beware the Jujub bird, and shun | ||
49 | The frumious Bandersnatch!' | ||
50 | |||
51 | He took his vorpal sword in hand: | ||
52 | Long time the manxome foe he sought -- | ||
53 | So rested he by the Tumtum gree, | ||
54 | And stood awhile in thought. | ||
55 | |||
56 | And as in uffish thought he stood, | ||
57 | The Jabberwock, with eyes of flame, | ||
58 | Came whiffling through the tulgey wook, | ||
59 | And burbled as it came! | ||
60 | |||
61 | One, two! One, two! And through and through | ||
62 | The vorpal blade went snicker-snack! | ||
63 | He left it dead, and with its head | ||
64 | He went galumphing back. | ||
65 | |||
66 | `And has thou slain the Jabberwock? | ||
67 | Come to my arms, my beamish boy! | ||
68 | O frabjous day! Calloh! Callay! | ||
69 | He chortled in his joy. | ||
70 | |||
71 | `Twas brillig, and the slithy toves | ||
72 | Did gyre and gimble in the wabe; | ||
73 | All mimsy were the borogoves, | ||
74 | And the mome raths outgrabe. | ||
75 | |||
76 | |||
77 | ]) | ||
78 | |||
79 | AT_CLEANUP | ||
80 |
testsuite/ufms.c
0 → 100644
1 | /* ufms.c - a test of "UNIX mailbox first message symptom" | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <unistd.h> | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <mailutils/mailutils.h> | ||
24 | |||
25 | /* UFMS, or "UNIX mailbox first message symptom", is a bug that | ||
26 | existed in all versions of Mailutils up to 2.2.1 and 2.9.90 | ||
27 | as of 2010-11-07. | ||
28 | |||
29 | Due to improperly designed expunge routine, the body of the very | ||
30 | first message in a UNIX mailbox would get corrupted under certain | ||
31 | circumstances. The following three lines would appear at the top | ||
32 | of the body: | ||
33 | |||
34 | -IMAPbase: X Y | ||
35 | Status: S | ||
36 | X-UID: Z | ||
37 | |||
38 | where (X, Y, Z are decimal numbers and S is a status string). | ||
39 | |||
40 | Prerequisites for triggering the bug: | ||
41 | |||
42 | 1. Mailbox contains more than one message. | ||
43 | 2. The first message does not carry X-IMAPbase and X-UID headers. | ||
44 | |||
45 | Recipe for triggering the bug: | ||
46 | |||
47 | 1. Delete some messages. | ||
48 | 2. Expunge the mailbox. | ||
49 | 3. Modify attributes of the first message. | ||
50 | 4. Flush your changes. | ||
51 | */ | ||
52 | |||
53 | |||
54 | int | ||
55 | main (int argc, char **argv) | ||
56 | { | ||
57 | mu_mailbox_t mbox; | ||
58 | size_t i, count; | ||
59 | mu_message_t msg; | ||
60 | mu_attribute_t attr; | ||
61 | |||
62 | if (argc != 2) | ||
63 | { | ||
64 | fprintf (stderr, "usage: %s MBOX\n", argv[0]); | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | mu_registrar_record (mu_mbox_record); | ||
69 | |||
70 | /* Open the mailbox */ | ||
71 | MU_ASSERT (mu_mailbox_create (&mbox, argv[1])); | ||
72 | MU_ASSERT (mu_mailbox_open (mbox, MU_STREAM_RDWR)); | ||
73 | mu_mailbox_messages_count (mbox, &count); | ||
74 | if (count < 2) | ||
75 | { | ||
76 | fprintf (stderr, | ||
77 | "%s: input mailbox should contain at least two messages\n", | ||
78 | argv[0]); | ||
79 | exit (1); | ||
80 | } | ||
81 | /* Delete all records except the first and expunge the mailbox. */ | ||
82 | for (i = 2; i <= count; i++) | ||
83 | { | ||
84 | MU_ASSERT (mu_mailbox_get_message (mbox, i, &msg)); | ||
85 | MU_ASSERT (mu_message_get_attribute (msg, &attr)); | ||
86 | MU_ASSERT (mu_attribute_set_deleted (attr)); | ||
87 | } | ||
88 | mu_mailbox_expunge (mbox); | ||
89 | |||
90 | /* Modify attributes on the remaining message and synch */ | ||
91 | MU_ASSERT (mu_mailbox_get_message (mbox, 1, &msg)); | ||
92 | MU_ASSERT (mu_message_get_attribute (msg, &attr)); | ||
93 | MU_ASSERT (mu_attribute_set_read (attr)); | ||
94 | mu_mailbox_sync (mbox); | ||
95 | |||
96 | /* Cleanup & exit */ | ||
97 | mu_mailbox_close (mbox); | ||
98 | mu_mailbox_destroy (&mbox); | ||
99 | return 0; | ||
100 | } |
-
Please register or sign in to post a comment