multiline: reject an over-limit batch with a FAIL instead of silently dropping the overflowing lines — accumulate() dropped a line that exceeded multiline_maxbytes/maxlines but still returned buffered=true, so the client believed a truncated message was sent whole; now overflow flags the batch and close() drops it with a standard FAIL

This commit is contained in:
Jean Chevronnet 2026-08-19 01:13:39 +00:00
parent 83cdce17c5
commit 14eb982db5

View file

@ -35,6 +35,7 @@ pub struct MlineBatch {
pub notice: bool, pub notice: bool,
pub parts: Vec<(String, bool)>, // (text, concat-with-previous-part) pub parts: Vec<(String, bool)>, // (text, concat-with-previous-part)
pub bytes: usize, pub bytes: usize,
pub overflowed: bool, // a line exceeded the byte/line limit — reject the whole batch
} }
/// uid -> its open batch. Stored in `Server.ext`. /// uid -> its open batch. Stored in `Server.ext`.
@ -52,6 +53,7 @@ fn open(s: &mut Server, uid: Uid, bref: &str, target: &str) {
notice: false, notice: false,
parts: Vec::new(), parts: Vec::new(),
bytes: 0, bytes: 0,
overflowed: false,
}, },
); );
} }
@ -74,6 +76,10 @@ pub fn accumulate(
mb.notice = notice; mb.notice = notice;
mb.bytes += text.len(); mb.bytes += text.len();
mb.parts.push((text.to_string(), concat)); mb.parts.push((text.to_string(), concat));
} else {
// over the byte/line budget — flag so close() rejects the whole batch
// rather than silently delivering a truncated message.
mb.overflowed = true;
} }
true true
} }
@ -90,6 +96,15 @@ fn close(s: &mut Server, uid: Uid, bref: &str) -> Option<(String, bool, Vec<Stri
_ => return None, _ => return None,
} }
let mb = store.0.remove(&uid)?; let mb = store.0.remove(&uid)?;
if mb.overflowed {
s.fail(
uid,
"BATCH",
"MULTILINE_INVALID",
"Multiline batch exceeded the size/line limit and was dropped.",
);
return None;
}
let mut lines: Vec<String> = Vec::new(); let mut lines: Vec<String> = Vec::new();
for (text, concat) in mb.parts { for (text, concat) in mb.parts {
if concat && !lines.is_empty() { if concat && !lines.is_empty() {