From bc50c3bf7f5eb63b7eb22a4a94ec01eb8ef57bd1 Mon Sep 17 00:00:00 2001 From: Mechiel Lukkien Date: Sun, 2 Mar 2025 16:46:06 +0100 Subject: [PATCH] In imapserver with RENAME of Inbox, we didn't check for the metadata quota. Rename of Inbox is special, it copies the mailbox including metadata. --- imapserver/metadata.go | 42 +++++++++++++++++++++++------------------- imapserver/server.go | 2 ++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/imapserver/metadata.go b/imapserver/metadata.go index 98f96a4..8806542 100644 --- a/imapserver/metadata.go +++ b/imapserver/metadata.go @@ -283,25 +283,7 @@ func (c *conn) cmdSetmetadata(tag, cmd string, p *parser) { xcheckf(err, "updating metadata annotation") } - // Check for total size. We allow a total of 1000 entries, with total capacity of 1MB. - // ../rfc/5464:383 - var n int - var size int - err := bstore.QueryTx[store.Annotation](tx).ForEach(func(a store.Annotation) error { - n++ - if n > metadataMaxKeys { - // ../rfc/5464:590 - xusercodeErrorf("METADATA TOOMANY", "too many metadata entries, 1000 allowed in total") - } - size += len(a.Key) + len(a.Value) - if size > metadataMaxSize { - // ../rfc/5464:585 We only have a max total size limit, not per entry. We'll - // mention the max total size. - xusercodeErrorf(fmt.Sprintf("METADATA MAXSIZE %d", metadataMaxSize), "metadata entry values too large, total maximum size is 1MB") - } - return nil - }) - xcheckf(err, "checking metadata annotation size") + c.xcheckMetadataSize(tx) // ../rfc/7162:1335 if mb.ID != 0 && modseq != 0 { @@ -316,3 +298,25 @@ func (c *conn) cmdSetmetadata(tag, cmd string, p *parser) { c.ok(tag, cmd) } + +func (c *conn) xcheckMetadataSize(tx *bstore.Tx) { + // Check for total size. We allow a total of 1000 entries, with total capacity of 1MB. + // ../rfc/5464:383 + var n int + var size int + err := bstore.QueryTx[store.Annotation](tx).ForEach(func(a store.Annotation) error { + n++ + if n > metadataMaxKeys { + // ../rfc/5464:590 + xusercodeErrorf("METADATA TOOMANY", "too many metadata entries, 1000 allowed in total") + } + size += len(a.Key) + len(a.Value) + if size > metadataMaxSize { + // ../rfc/5464:585 We only have a max total size limit, not per entry. We'll + // mention the max total size. + xusercodeErrorf(fmt.Sprintf("METADATA MAXSIZE %d", metadataMaxSize), "metadata entry values too large, total maximum size is 1MB") + } + return nil + }) + xcheckf(err, "checking metadata annotation size") +} diff --git a/imapserver/server.go b/imapserver/server.go index 6c6c2a6..eb702e6 100644 --- a/imapserver/server.go +++ b/imapserver/server.go @@ -3037,6 +3037,8 @@ func (c *conn) cmdRename(tag, cmd string, p *parser) { xcheckf(err, "copy annotation to destination mailbox") } + c.xcheckMetadataSize(tx) + changes[0] = store.ChangeRemoveUIDs{MailboxID: srcMB.ID, UIDs: oldUIDs, ModSeq: modseq} changes[1] = store.ChangeAddMailbox{Mailbox: dstMB, Flags: dstFlags, ModSeq: modseq} // changes[2:...] are ChangeAddUIDs