From 2ac978ce54d32770049d8dc81dbb8ecc01d81c9f Mon Sep 17 00:00:00 2001
From: Harrison Booth <73434116+Harrison-Booth@users.noreply.github.com>
Date: Wed, 28 Oct 2026 14:49:53 -0500
Subject: [PATCH] dc5-02: enforce clipboard HTML size cap
---
crates/engine/src/cmd/richclip.rs | 114 ++++++++++++++++++++++++------
1 file changed, 94 insertions(+), 20 deletions(-)
diff --git a/crates/engine/src/cmd/richclip.rs b/crates/engine/src/cmd/richclip.rs
index 5b9eaf6d..063bd392 100644
--- a/crates/engine/src/cmd/richclip.rs
+++ b/crates/engine/src/cmd/richclip.rs
@@ -14,27 +14,97 @@ const MAX_RUNS: usize = 10_000;
pub fn body_to_html(body: &TextBody) -> String {
let mut out = String::new();
for (i, p) in body.paragraphs.iter().enumerate() {
- if i > 0 {
- out.push_str("
");
+ let prefix = if i > 0 { "
" } else { "
" }; + if !push_if_fits(&mut out, prefix, 4) { + return plain_html(body); } - out.push_str("
");
for r in &p.runs {
let (open, close) = tags(&r.props);
- out.push_str(&open);
+ if !push_if_fits(&mut out, &open, close.len() + 4) {
+ return plain_html(body);
+ }
match &r.kind {
- deckcraft_model::text::RunKind::Break => out.push_str("
"),
- _ => push_escaped(&mut out, &r.text),
+ deckcraft_model::text::RunKind::Break => {
+ if !push_if_fits(&mut out, "
", close.len() + 4) {
+ return plain_html(body);
+ }
+ }
+ _ => {
+ if !push_escaped_bounded(&mut out, &r.text, close.len() + 4) {
+ return plain_html(body);
+ }
+ }
}
out.push_str(&close);
- if out.len() > MAX_HTML {
- break;
- }
}
out.push_str("
" } else { "
" };
+ if !push_if_fits(&mut out, prefix, 4) {
+ break;
+ }
+ let mut complete = true;
+ for r in &p.runs {
+ if matches!(&r.kind, deckcraft_model::text::RunKind::Break) {
+ complete = push_if_fits(&mut out, "
", 4);
+ } else {
+ complete = push_escaped_bounded(&mut out, &r.text, 4);
+ }
+ if !complete {
+ break;
+ }
+ }
+ out.push_str("