diff options
Diffstat (limited to 'src/daemon.rs')
| -rw-r--r-- | src/daemon.rs | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/src/daemon.rs b/src/daemon.rs index 313a4aa..c578e5c 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -6,7 +6,7 @@ //! over a Unix socket using a line-oriented text protocol //! (see [`crate::protocol`]). -use std::io::{BufRead, BufReader, Write}; +use std::io::{BufRead, BufReader, Read, Write}; use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc; @@ -196,7 +196,7 @@ fn republish(node: &mut Node, store: &PasteStore) { .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_secs(); - let expires = paste.created_at + paste.ttl_secs; + let expires = paste.created_at.saturating_add(paste.ttl_secs); let rem = expires.saturating_sub(now); std::cmp::min(rem, u16::MAX as u64) as u16 }; @@ -259,6 +259,10 @@ pub fn run_unix_listener( let _ = std::fs::remove_file(sock_path); } +/// Maximum protocol line size (128 KiB covers the 64 KiB paste +/// limit after base58 expansion plus command overhead). +const MAX_LINE_SIZE: usize = 128 * 1024; + /// Read requests line-by-line from a connected Unix socket /// client, forwarding each to the daemon main loop via `tx`. fn handle_client( @@ -268,11 +272,29 @@ fn handle_client( stream.set_nonblocking(false)?; stream.set_read_timeout(Some(Duration::from_secs(60)))?; - let reader = BufReader::new(&stream); + let mut reader = BufReader::new(&stream); let mut writer = &stream; - - for line in reader.lines() { - let line = line?; + let mut line = String::new(); + + loop { + line.clear(); + // Limit read to MAX_LINE_SIZE to prevent a client from + // exhausting memory with an unbounded request line. + let n = (&mut reader).take(MAX_LINE_SIZE as u64).read_line(&mut line)?; + if n == 0 { + break; + } + if !line.ends_with('\n') && n >= MAX_LINE_SIZE { + let resp = protocol::format_response(&Response::Err( + "request too large".into(), + )); + writer.write_all(resp.as_bytes())?; + // Drain remaining bytes until newline + let mut discard = String::new(); + let _ = reader.read_line(&mut discard); + continue; + } + let line = line.trim(); let cmd = match protocol::parse_request(&line) { Ok(c) => c, Err(e) => { |