aboutsummaryrefslogtreecommitdiffstats
path: root/src/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.rs')
-rw-r--r--src/daemon.rs34
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) => {