diff --git a/crates/loro-internal/src/handler.rs b/crates/loro-internal/src/handler.rs index 02ade94a..f0dba4fa 100644 --- a/crates/loro-internal/src/handler.rs +++ b/crates/loro-internal/src/handler.rs @@ -620,6 +620,13 @@ impl ListHandler { pos: usize, c_type: ContainerType, ) -> LoroResult { + if pos > self.len() { + return Err(LoroError::OutOfBound { + pos, + len: self.len(), + }); + } + let id = txn.next_id(); let container_id = ContainerID::new_normal(id, c_type); let child_idx = txn.arena.register_container(&container_id); diff --git a/crates/loro-internal/tests/test.rs b/crates/loro-internal/tests/test.rs index 37b60be7..2268a181 100644 --- a/crates/loro-internal/tests/test.rs +++ b/crates/loro-internal/tests/test.rs @@ -6,6 +6,37 @@ use loro_internal::{ }; use serde_json::json; +#[test] +fn out_of_bound_test() { + let a = LoroDoc::new_auto_commit(); + a.get_text("text").insert_(0, "Hello").unwrap(); + a.get_list("list").insert_(0, "Hello".into()).unwrap(); + a.get_list("list").insert_(1, "Hello".into()).unwrap(); + // expect out of bound err + let err = a.get_text("text").insert_(6, "Hello").unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); + let err = a.get_text("text").delete_(3, 5).unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); + let err = a + .get_text("text") + .mark_(0, 8, "h", 5.into(), TextStyleInfoFlag::BOLD) + .unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); + let _err = a + .get_text("text") + .mark_(3, 0, "h", 5.into(), TextStyleInfoFlag::BOLD) + .unwrap_err(); + let err = a.get_list("list").insert_(6, "Hello".into()).unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); + let err = a.get_list("list").delete_(3, 2).unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); + let err = a + .get_list("list") + .insert_container_(3, ContainerType::Map) + .unwrap_err(); + assert!(matches!(err, loro_common::LoroError::OutOfBound { .. })); +} + #[test] fn list() { let a = LoroDoc::new_auto_commit();