From a883d6b2d95e48731b93aaa9d211f6a875493fc4 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 7 Nov 2026 08:14:47 +0000 Subject: [PATCH] Reject invalid index in shape.adjust and shape.quickStyle Found while testing crates/engine/src/cmd/shape/appearance.rs:8 (adjust, index via usize_param); same pattern in quick_style at :559 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/shape.rs | 2 +- crates/engine/src/cmd/shape/appearance.rs | 6 +++--- crates/engine/src/tests.rs | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/crates/engine/src/cmd/shape.rs b/crates/engine/src/cmd/shape.rs index a447a20b9..78b6204bb 100644 --- a/crates/engine/src/cmd/shape.rs +++ b/crates/engine/src/cmd/shape.rs @@ -10,7 +10,7 @@ use serde_json::{Value, json}; use super::{ CommandSpec, NO_ID_SPACE, bad, bool_or, bool_param, cmd, color_param, color_value, edit_geometry, edit_shapes, f64_param, has_selection, - has_slide, id_param, ok, str_param, targets, usize_param, with_param, xfrm_of, + has_slide, id_param, ok, opt_usize_param, str_param, targets, usize_param, with_param, xfrm_of, }; use crate::{Result, Session}; diff --git a/crates/engine/src/cmd/shape/appearance.rs b/crates/engine/src/cmd/shape/appearance.rs index c515d2b2c..4dd406ea3 100644 --- a/crates/engine/src/cmd/shape/appearance.rs +++ b/crates/engine/src/cmd/shape/appearance.rs @@ -1,11 +1,11 @@ use super::{ ColorRef, ColorTransform, Dash, Effects, Fill, Geom, Glow, Gradient, GradientShape, GradientStop, Line, LineEnd, PictureFill, PictureMode, Reflection, Result, Rgba, SchemeSlot, Session, Shadow, ShapeStyle, Value, apply_fill, bad, bool_or, color_param, color_value, edit_geometry, - edit_shapes, f64_param, inherited_fills, json, requested_fill, str_param, targets, usize_param, + edit_shapes, f64_param, inherited_fills, json, opt_usize_param, requested_fill, str_param, targets, }; pub(super) fn adjust(s: &mut Session, p: &Value) -> Result { - let i = usize_param(p, "index").unwrap_or(0).min(16); + let i = opt_usize_param(p, "index", "shape.adjust")?.unwrap_or(0).min(16); let v = f64_param(p, "value").ok_or_else(|| bad("shape.adjust", "missing `value`"))?; edit_geometry(s, p, "shape.adjust", |sh| { if let Geom::Preset { name, adj } = &mut sh.geom { @@ -556,7 +556,7 @@ pub fn quick_style_for(index: usize) -> (ShapeStyle, Option, Option) } pub(super) fn quick_style(s: &mut Session, p: &Value) -> Result { - let i = usize_param(p, "index").unwrap_or(1).min(41); + let i = opt_usize_param(p, "index", "shape.quickStyle")?.unwrap_or(1).min(41); let (st, f, l) = quick_style_for(i); edit_shapes(s, p, "shape.quickStyle", |sh| { sh.style = Some(st.clone()); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index ca1f93d26..7d55a9b16 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -7029,3 +7029,18 @@ fn outline_export_skips_footer_date_and_slide_number() { assert!(rtf.contains("Agenda") && rtf.contains("First point"), "{rtf:?}"); assert!(!rtf.contains("Company Confidential") && !rtf.contains("1 May 2026"), "{rtf:?}"); } + +#[test] +fn shape_adjust_and_quick_style_reject_invalid_index() { + let mut s = session(); + let r = s.execute("shape.insert", &json!({"preset": "roundRect", "rect": [100, 100, 200, 100]})).unwrap(); + let id = deckcraft_model::ShapeId(r["id"].as_u64().unwrap() as u32); + let before = s.doc().unwrap().shape(id).unwrap().clone(); + for bad in [json!(-1), json!(1.5)] { + assert!(s.execute("shape.adjust", &json!({"index": bad, "value": 0.4})).is_err(), "adjust accepted {bad}"); + assert!(s.execute("shape.quickStyle", &json!({"index": bad})).is_err(), "quickStyle accepted {bad}"); + } + assert_eq!(s.doc().unwrap().shape(id).unwrap().geom, before.geom); + assert_eq!(s.doc().unwrap().shape(id).unwrap().style, before.style); + s.execute("shape.adjust", &json!({"value": 0.4})).unwrap(); +}