IMAP: Check buf size before pushing escape sequences within quoted literals
This commit is contained in:
@@ -26,9 +26,9 @@ If you are upgrading from v0.11.x or v0.12.x, this version includes **breaking c
|
|||||||
- IMAP: Include `administer` permission in ACL responses.
|
- IMAP: Include `administer` permission in ACL responses.
|
||||||
- IMAP: Add owner rights to ACL get responses.
|
- IMAP: Add owner rights to ACL get responses.
|
||||||
- IMAP: Do not auto-train Bayes when moving messages from Junk to Trash.
|
- IMAP: Do not auto-train Bayes when moving messages from Junk to Trash.
|
||||||
- IMAP/ManageSieve: Increase maximum quoted argument size (fixes #2039).
|
- IMAP/ManageSieve: Increase maximum quoted argument size (#2039).
|
||||||
- CalDAV: Limit recurrence expansions in calendar reports.
|
- CalDAV: Limit recurrence expansions in calendar reports ([CVE-2025-59045](https://github.com/stalwartlabs/stalwart/security/advisories/GHSA-xv4r-q6gr-6pfg)).
|
||||||
- WebDAV: Do not fix percent encoding on WebDAV FS (closes #2036).
|
- WebDAV: Do not fix percent encoding on WebDAV FS (#2036).
|
||||||
|
|
||||||
## [0.13.2] - 2025-07-28
|
## [0.13.2] - 2025-07-28
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use super::{ResponseCode, ResponseType};
|
||||||
|
use compact_str::{CompactString, format_compact};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use compact_str::{CompactString, format_compact};
|
const QUOTED_ARG_MAX_LEN: usize = 4096;
|
||||||
|
|
||||||
use super::{ResponseCode, ResponseType};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -277,7 +277,7 @@ impl<T: CommandParser> Receiver<T> {
|
|||||||
if !escaped {
|
if !escaped {
|
||||||
self.push_argument(true)?;
|
self.push_argument(true)?;
|
||||||
self.state = State::Argument { last_ch: b' ' };
|
self.state = State::Argument { last_ch: b' ' };
|
||||||
} else if self.buf.len() < 4096 {
|
} else if self.buf.len() < QUOTED_ARG_MAX_LEN {
|
||||||
self.buf.push(ch);
|
self.buf.push(ch);
|
||||||
self.state = State::ArgumentQuoted { escaped: false };
|
self.state = State::ArgumentQuoted { escaped: false };
|
||||||
} else {
|
} else {
|
||||||
@@ -286,7 +286,11 @@ impl<T: CommandParser> Receiver<T> {
|
|||||||
}
|
}
|
||||||
b'\\' => {
|
b'\\' => {
|
||||||
if escaped {
|
if escaped {
|
||||||
self.buf.push(ch);
|
if self.buf.len() < QUOTED_ARG_MAX_LEN {
|
||||||
|
self.buf.push(ch);
|
||||||
|
} else {
|
||||||
|
return Err(self.error_reset("Quoted argument too long."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.state = State::ArgumentQuoted { escaped: !escaped };
|
self.state = State::ArgumentQuoted { escaped: !escaped };
|
||||||
}
|
}
|
||||||
@@ -294,7 +298,7 @@ impl<T: CommandParser> Receiver<T> {
|
|||||||
return Err(self.error_reset("Unterminated quoted argument."));
|
return Err(self.error_reset("Unterminated quoted argument."));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if self.buf.len() < 4096 {
|
if self.buf.len() < QUOTED_ARG_MAX_LEN {
|
||||||
if escaped {
|
if escaped {
|
||||||
self.buf.push(b'\\');
|
self.buf.push(b'\\');
|
||||||
}
|
}
|
||||||
@@ -340,7 +344,6 @@ impl<T: CommandParser> Receiver<T> {
|
|||||||
self.buf.push(ch);
|
self.buf.push(ch);
|
||||||
} else {
|
} else {
|
||||||
// Digit found after non-sync '+' flag
|
// Digit found after non-sync '+' flag
|
||||||
|
|
||||||
return Err(self.error_reset("Invalid literal."));
|
return Err(self.error_reset("Invalid literal."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ async fn limits() {
|
|||||||
// Exceed max line length
|
// Exceed max line length
|
||||||
let mut session = Session::test_with_shutdown(TestSMTP::from_core(core).server, rx);
|
let mut session = Session::test_with_shutdown(TestSMTP::from_core(core).server, rx);
|
||||||
session.data.remote_ip_str = "10.0.0.1".into();
|
session.data.remote_ip_str = "10.0.0.1".into();
|
||||||
let mut buf = vec![b'A'; 2049];
|
let mut buf = vec![b'A'; 4097];
|
||||||
session.ingest(&buf).await.unwrap();
|
session.ingest(&buf).await.unwrap();
|
||||||
session.ingest(b"\r\n").await.unwrap();
|
session.ingest(b"\r\n").await.unwrap();
|
||||||
session.response().assert_code("554 5.3.4");
|
session.response().assert_code("554 5.3.4");
|
||||||
|
|||||||
Reference in New Issue
Block a user