Refuse negative or fractional indexes in page.select and doc.switch

Found while testing crates/engine/src/cmd/page.rs:50

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-15 08:02:06 +02:00
co-authored by Claude Haiku 5.5
parent 8482c3e85b
commit 7f2f8ee09a
3 changed files with 19 additions and 2 deletions
+1 -1
View File
@@ -219,7 +219,7 @@ pub fn specs() -> Vec<CommandSpec> {
}
),
spec!("doc.switch", "Switch document", "{index}", false, |s, p| {
let i = req_num("doc.switch", p, "index")? as usize;
let i = req_index("doc.switch", p, "index")?;
if i >= s.docs.len() {
return Err(bad("doc.switch", "no such document"));
}
+1 -1
View File
@@ -47,7 +47,7 @@ pub fn specs() -> Vec<CommandSpec> {
let id = match id(p, "id") {
Some(i) => i,
None => {
let k = req_num("page.select", p, "index")? as usize;
let k = req_index("page.select", p, "index")?;
*doc.pages.get(k).ok_or_else(|| bad("page.select", "no such page"))?
}
};
@@ -337,6 +337,23 @@ fn pages_by_the_documented_rules() {
assert_ne!(s.page().unwrap(), div, "deleting the open page opens a page, never a divider");
}
#[test]
fn page_select_and_doc_switch_refuse_negative_or_fractional_indexes() {
let mut s = Session::new();
let p2 = id(&ex(&mut s, "page.add", json!({})));
for bad_index in [json!(-1), json!(0.5)] {
assert!(s.execute("page.select", &json!({"index": bad_index})).is_err(), "page.select index {bad_index} must fail");
assert_eq!(s.page().unwrap(), p2, "page.select index {bad_index} leaves the open page alone");
}
ex(&mut s, "file.new", json!({}));
let active = s.active;
assert_eq!(active, 1);
for bad_index in [json!(-1), json!(0.5)] {
assert!(s.execute("doc.switch", &json!({"index": bad_index})).is_err(), "doc.switch index {bad_index} must fail");
assert_eq!(s.active, active, "doc.switch index {bad_index} leaves the active tab alone");
}
}
#[test]
fn assets_panel_lists_files_and_drops_by_the_documented_rules() {
let mut s = Session::new();