ref: f8700ea1a8bb5fa62cc4860c5756a8a3ef65c29f
parent: a32f464057acca8738c631add1f8569691b179aa
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Oct 10 14:49:24 EDT 2025
upas/fs: handle unsolicited expunge messages correctly when a different client deletes a message that we haven't added to the current set of message mid-sync, we would return an error, leaving the response queued; this would cause the next fetch to get the response for the previous fetch request, offsetting the message bodies by one. Additionally, we were using 'nmsg' and not 'muid' when expunging, but 'nmsg' could be modified by other unsolicited messages; this could lead us to indexing out of bounds when moving the messages.
--- a/sys/src/cmd/upas/fs/imap.c
+++ b/sys/src/cmd/upas/fs/imap.c
@@ -341,7 +341,7 @@
extern void msgrealloc(Message*, ulong);
if(idx < 0 || idx >= imap->muid){
- snprint(error, sizeof error, "fetchrsp: bad idx %d", idx);
+ snprint(error, sizeof error, "fetchrsp: bad idx %d [message %s]", idx, p);
return error;
}
@@ -516,12 +516,13 @@
imap->nuid = n;
break;
case Expunge:
- if(n < 1 || n > imap->muid || (n - 1) >= imap->nmsg){
- snprint(error, sizeof(error), "bad expunge %d (nmsg %d)", n, imap->nuid);
- return error;
+ if(n < 1 || n > imap->muid){
+ fprint(2, "unknown message for expunge: %d", n);
+ break;
}
idx = n - 1;
- memmove(&imap->f[idx], &imap->f[idx + 1], (imap->nmsg - idx - 1)*sizeof(imap->f[0]));
+ memmove(&imap->f[idx], &imap->f[idx + 1], (imap->muid - idx - 1)*sizeof(imap->f[0]));
+ imap->muid--;
imap->nmsg--;
imap->nuid--;
break;
--
⑨