Refuse an empty JMAP id instead of reading it as id 0
ci / github (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / fork-checks (pull_request) Failing after 50s
ci / build (pull_request) Canceled after 5m40s

An Email/set with mailboxIds {"": true} was accepted and filed the
message in the Inbox. Id::from_str returned 0 for an empty string, and
document 0 is each collection's first: the Inbox for mail. RFC 8620
§1.2 ids are 1 to 255 characters, so "" is refused now, and every
caller already treats a refused id as invalid or not found.

Over-long ids still parse as they did; upstream's test accepts them on
purpose. Found while probing group mailboxes on a scratch server
(specs/multi-account.md, G3).

types tests, jmap_tests and imap_tests pass (RocksDB).
This commit is contained in:
jcoffey-dev committed 2026-10-05 14:15:39 -07:00
1 parent d7bebd454d
commit 9429f1de00
1 file changed
+13
+13
View File
@@ -36,6 +36,13 @@ impl FromStr for Id {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
// inbuxa: an empty id is not id 0. RFC 8620 §1.2 ids are 1 to 255
// characters, and "" would otherwise name each collection's first
// document: `mailboxIds: {"": true}` filed a message in the Inbox.
if s.is_empty() {
return Err(());
}
let mut id = 0;
for &ch in s.as_bytes() {
@@ -261,4 +268,10 @@ mod tests {
Id::from_str("p333333333333p333333333333").unwrap();
}
#[test]
fn empty_jmap_id_is_refused() {
assert!(Id::from_str("").is_err());
assert_eq!(Id::from_str("a").unwrap(), Id::from(0u64));
}
}