From 290f53c38cdacd502eb6dda52f2ad207063e3973 Mon Sep 17 00:00:00 2001 From: murilo ijanc Date: Wed, 25 Mar 2026 15:41:40 -0300 Subject: Limit stdin read in tp, bound protocol drain, document Arc leak - tp: limit stdin to 64 KiB + 1 byte to reject oversized pastes early without unbounded memory allocation - daemon: bound the oversized-line drain to MAX_LINE_SIZE so a client without newlines cannot block beyond the read timeout - tpd: document intentional Arc::into_raw leak in signal handler --- src/bin/tp.rs | 27 ++++++++++++++++++++------- src/bin/tpd.rs | 4 +++- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'src/bin') diff --git a/src/bin/tp.rs b/src/bin/tp.rs index 860d1c9..5c4c473 100644 --- a/src/bin/tp.rs +++ b/src/bin/tp.rs @@ -110,14 +110,27 @@ fn main() { std::process::exit(1); } }; + // Read at most MAX_PASTE + 1 byte so we can detect + // oversized input without unbounded allocation. + const MAX_PASTE: usize = 64 * 1024; let mut content = Vec::new(); - if let Err(e) = std::io::stdin().read_to_end(&mut content) { - eprintln!("error: reading stdin: {e}"); - std::process::exit(1); - } - if content.is_empty() { - eprintln!("error: empty input"); - std::process::exit(1); + match std::io::stdin() + .take((MAX_PASTE + 1) as u64) + .read_to_end(&mut content) + { + Ok(0) => { + eprintln!("error: empty input"); + std::process::exit(1); + } + Ok(n) if n > MAX_PASTE => { + eprintln!("error: input exceeds 64 KiB limit"); + std::process::exit(1); + } + Err(e) => { + eprintln!("error: reading stdin: {e}"); + std::process::exit(1); + } + _ => {} } let cmd = if public { "PUTP" } else { "PUT" }; format!("{cmd} {ttl_secs} {}\n", base58::encode(&content)) diff --git a/src/bin/tpd.rs b/src/bin/tpd.rs index a1edf79..e1ebc7b 100644 --- a/src/bin/tpd.rs +++ b/src/bin/tpd.rs @@ -256,7 +256,9 @@ fn main() { let shutdown = Arc::new(AtomicBool::new(false)); - // Signal handler + // Signal handler — Arc::into_raw intentionally leaks the + // refcount so the pointer remains valid for the process + // lifetime. No matching Arc::from_raw needed. let sig = Arc::clone(&shutdown); unsafe { SHUTDOWN_PTR.store( -- cgit v1.2.3