From 968eb67d075e5a5ad13a8ad1f1626522d6f089a9 Mon Sep 17 00:00:00 2001 From: Manuel Raimann Date: Thu, 12 Feb 2026 13:54:19 +0100 Subject: [PATCH] fix: return error instead of panicking on out-of-bounds categorical index --- src/parameter.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/parameter.rs b/src/parameter.rs index c266034..74782f8 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -467,7 +467,11 @@ impl Parameter for CategoricalParam { fn cast_param_value(&self, param_value: &ParamValue) -> Result { match param_value { - ParamValue::Categorical(index) => Ok(self.choices[*index].clone()), + ParamValue::Categorical(index) => self + .choices + .get(*index) + .cloned() + .ok_or(Error::Internal("categorical index out of bounds")), _ => Err(Error::Internal( "Categorical distribution should return Categorical value", )), @@ -708,7 +712,8 @@ impl Parameter for EnumParam { fn cast_param_value(&self, param_value: &ParamValue) -> Result { match param_value { - ParamValue::Categorical(index) => Ok(T::from_index(*index)), + ParamValue::Categorical(index) if *index < T::N_CHOICES => Ok(T::from_index(*index)), + ParamValue::Categorical(_) => Err(Error::Internal("categorical index out of bounds")), _ => Err(Error::Internal( "Categorical distribution should return Categorical value", )), @@ -887,6 +892,17 @@ mod tests { assert!(param.cast_param_value(&ParamValue::Float(1.0)).is_err()); } + #[test] + fn categorical_param_cast_out_of_bounds() { + let param = CategoricalParam::new(vec!["sgd", "adam", "rmsprop"]); + assert!(param.cast_param_value(&ParamValue::Categorical(3)).is_err()); + assert!( + param + .cast_param_value(&ParamValue::Categorical(usize::MAX)) + .is_err() + ); + } + #[test] fn bool_param_distribution() { let param = BoolParam::new(); @@ -955,6 +971,17 @@ mod tests { assert!(param.cast_param_value(&ParamValue::Float(1.0)).is_err()); } + #[test] + fn enum_param_cast_out_of_bounds() { + let param = EnumParam::::new(); + assert!(param.cast_param_value(&ParamValue::Categorical(3)).is_err()); + assert!( + param + .cast_param_value(&ParamValue::Categorical(usize::MAX)) + .is_err() + ); + } + #[test] fn float_param_suggest_via_trial() { let param = FloatParam::new(0.0, 1.0);