From 78f0cbc2e59ea087a5a87d8caf5fd805cdb4655e Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 2 Jun 2026 11:34:23 -0400 Subject: [PATCH] init: accept colon-separated rlimits and strip outer quotes Two issues with apply_rlimits(): 1. The C init parsed KRUN_RLIMITS with strtoull() and a single-char skip, so any separator character between ID, CUR, and MAX worked (e.g. "7:1024:4096"). The Rust code required "ID=CUR:MAX" and silently skipped entries using the historical colon-only format. 2. krun_set_rlimits() wraps the entire value in double-quotes (format!("\"{}\"", ...)), so the env var received by init is "\"7=1024:4096\"". Neither the old Rust nor the C parser handled this correctly. Fix both by extracting parse_rlimit_entry() which strips outer '"' chars and splits on the first two occurrences of '=' or ':' via splitn(3). Both formats and the quoted form now parse correctly. Assisted-by: Claude Code: claude-sonnet-4-6 Signed-off-by: Jake Correnti --- init/src/env.rs | 79 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/init/src/env.rs b/init/src/env.rs index 5e4ec50..29bc998 100644 --- a/init/src/env.rs +++ b/init/src/env.rs @@ -192,24 +192,65 @@ pub fn apply_rlimits() { let Ok(rlimits) = env::var("KRUN_RLIMITS") else { return; }; - for item in rlimits.split(',') { - let Some((id_s, rest)) = item.split_once('=') else { - continue; - }; - let Some((cur_s, max_s)) = rest.split_once(':') else { - continue; - }; - let (Ok(id), Ok(cur), Ok(max)) = ( - id_s.parse::(), - cur_s.parse::(), - max_s.parse::(), - ) else { - continue; - }; - let rlim = libc::rlimit { - rlim_cur: cur, - rlim_max: max, - }; - unsafe { libc::setrlimit(id as _, &rlim) }; + // krun_set_rlimits() wraps the value in outer double-quotes; strip them. + let s = rlimits.trim_matches('"'); + for item in s.split(',') { + if let Some((id, cur, max)) = parse_rlimit_entry(item) { + let rlim = libc::rlimit { + rlim_cur: cur, + rlim_max: max, + }; + unsafe { libc::setrlimit(id as _, &rlim) }; + } + } +} + +// Accept both "ID=CUR:MAX" (Rust format) and "ID:CUR:MAX" (C format) by +// splitting on the first two occurrences of either '=' or ':'. +fn parse_rlimit_entry(item: &str) -> Option<(u32, libc::rlim_t, libc::rlim_t)> { + let item = item.trim_matches('"'); + let parts: Vec<&str> = item.splitn(3, ['=', ':']).collect(); + let [id, cur, max] = parts.as_slice() else { + return None; + }; + let id = id.parse::().ok()?; + let cur = cur.parse::().ok()?; + let max = max.parse::().ok()?; + Some((id, cur, max)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rlimit_equals_format() { + assert_eq!(parse_rlimit_entry("7=1024:4096"), Some((7, 1024, 4096))); + } + + #[test] + fn rlimit_colon_format() { + assert_eq!(parse_rlimit_entry("7:1024:4096"), Some((7, 1024, 4096))); + } + + #[test] + fn rlimit_outer_quotes_stripped() { + assert_eq!(parse_rlimit_entry("\"7=1024:4096\""), Some((7, 1024, 4096))); + } + + #[test] + fn rlimit_trailing_quote_stripped() { + // Last item in a quoted list has a trailing '"'. + assert_eq!(parse_rlimit_entry("11=512:1024\""), Some((11, 512, 1024))); + } + + #[test] + fn rlimit_too_few_parts_is_none() { + assert_eq!(parse_rlimit_entry("7:1024"), None); + } + + #[test] + fn rlimit_non_numeric_is_none() { + assert_eq!(parse_rlimit_entry("invalid"), None); } } -- 2.51.2