diff --git a/crates/ember-protocol/src/command.rs b/crates/ember-protocol/src/command.rs index 9fa3fb6e..be62dfc2 100644 --- a/crates/ember-protocol/src/command.rs +++ b/crates/ember-protocol/src/command.rs @@ -1189,9 +1189,9 @@ fn parse_f64(frame: &Frame, cmd: &str) -> Result { let v = s.parse::().map_err(|_| { ProtocolError::InvalidCommandFrame(format!("value is not a valid float for '{cmd}'")) })?; - if v.is_nan() { + if v.is_nan() || v.is_infinite() { return Err(ProtocolError::InvalidCommandFrame(format!( - "NaN is not a valid score for '{cmd}'" + "value is not a valid finite float for '{cmd}'" ))); } Ok(v) @@ -1643,6 +1643,11 @@ fn parse_slot_list(args: &[Frame]) -> Result, ProtocolError> { let slot: u16 = slot_str .parse() .map_err(|_| ProtocolError::InvalidCommandFrame("invalid slot number".into()))?; + if slot >= 16384 { + return Err(ProtocolError::InvalidCommandFrame(format!( + "invalid slot {slot}: must be 0-16383" + ))); + } slots.push(slot); } Ok(slots) @@ -1657,6 +1662,11 @@ fn parse_cluster_setslot(args: &[Frame]) -> Result { let slot: u16 = slot_str .parse() .map_err(|_| ProtocolError::InvalidCommandFrame("invalid slot number".into()))?; + if slot >= 16384 { + return Err(ProtocolError::InvalidCommandFrame(format!( + "invalid slot {slot}: must be 0-16383" + ))); + } if args.len() < 2 { return Err(ProtocolError::WrongArity("CLUSTER SETSLOT".into())); @@ -1825,10 +1835,15 @@ fn parse_vadd(args: &[Frame]) -> Result { let key = extract_string(&args[0])?; let element = extract_string(&args[1])?; - // parse vector values until we hit a non-numeric argument or end + // parse vector values until we hit a non-numeric argument, end, or dim limit let mut idx = 2; let mut vector = Vec::new(); while idx < args.len() { + if vector.len() >= MAX_VECTOR_DIMS { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VADD: vector exceeds {MAX_VECTOR_DIMS} dimensions" + ))); + } let s = extract_string(&args[idx])?; if let Ok(v) = s.parse::() { vector.push(v); @@ -1844,13 +1859,6 @@ fn parse_vadd(args: &[Frame]) -> Result { )); } - if vector.len() > MAX_VECTOR_DIMS { - return Err(ProtocolError::InvalidCommandFrame(format!( - "VADD: vector has {} dimensions, max is {MAX_VECTOR_DIMS}", - vector.len() - ))); - } - // parse optional flags let mut metric: u8 = 0; // cosine default let mut quantization: u8 = 0; // f32 default @@ -1960,10 +1968,15 @@ fn parse_vsim(args: &[Frame]) -> Result { let key = extract_string(&args[0])?; - // parse query vector until we hit a non-numeric argument + // parse query vector until we hit a non-numeric argument, end, or dim limit let mut idx = 1; let mut query = Vec::new(); while idx < args.len() { + if query.len() >= MAX_VECTOR_DIMS { + return Err(ProtocolError::InvalidCommandFrame(format!( + "VSIM: query exceeds {MAX_VECTOR_DIMS} dimensions" + ))); + } let s = extract_string(&args[idx])?; if let Ok(v) = s.parse::() { query.push(v); @@ -1979,13 +1992,6 @@ fn parse_vsim(args: &[Frame]) -> Result { )); } - if query.len() > MAX_VECTOR_DIMS { - return Err(ProtocolError::InvalidCommandFrame(format!( - "VSIM: query has {} dimensions, max is {MAX_VECTOR_DIMS}", - query.len() - ))); - } - // COUNT k is required let mut count: Option = None; let mut ef_search: usize = 0;