Delete::delete panics instead of returning None when a pointer's final token indexes one past the end of an array. The RFC 6901 - token always resolves to that index, so a pointer parsed from untrusted input reaches the panic, for example a JSON Patch remove op with path /-.
Version and features
jsonptr 0.7.1 with default features. The reproducer needs the json and delete features, both of which are on by default. It also needs serde_json as a direct dependency:
[dependencies]
jsonptr = "=0.7.1"
serde_json = "1"
Reproducer
use jsonptr::{delete::Delete, Pointer};
use serde_json::json;
fn main() {
let mut doc = json!([1, 2, 3]);
let removed = doc.delete(Pointer::from_static("/-"));
println!("{removed:?}");
}
Observed
Panic with removal index (is 3) should be < len (is 3), in debug and release alike.
Expected
None, with the document unmodified. The delete module docs (src/delete.rs:8-10) and Pointer::delete docs (src/pointer.rs:400-401) both say "If the Pointer fails to resolve for any reason, Ok(None) is returned." Delete::delete returns Option<Value> and documents no panic. src/index.rs:5-7 says "attempting to use - to resolve an array value will always be out of bounds", so it should miss rather than crash. The control case /5 on a 3-element array does return None.
Root cause
src/delete.rs:108 calls for_len_incl. That helper admits index == len and maps Index::Next to len. The next line passes the result to Vec::remove, which requires index < len. resolve uses the exclusive helper for_len at src/resolve.rs:293. The toml impl repeats the same call at src/delete.rs:146.
Scope
Any pointer whose last token resolves to an array index equal to that array's length. That covers - on any array and a numeric index equal to the length, including /0 on an empty array. Nested arrays hit it too: /foo/- on {"foo": [1, 2]} panics. The test suite has no out-of-bounds array delete case.
Delete::deletepanics instead of returningNonewhen a pointer's final token indexes one past the end of an array. The RFC 6901-token always resolves to that index, so a pointer parsed from untrusted input reaches the panic, for example a JSON Patchremoveop with path/-.Version and features
jsonptr 0.7.1 with default features. The reproducer needs the
jsonanddeletefeatures, both of which are on by default. It also needsserde_jsonas a direct dependency:Reproducer
Observed
Panic with
removal index (is 3) should be < len (is 3), in debug and release alike.Expected
None, with the document unmodified. The delete module docs (src/delete.rs:8-10) andPointer::deletedocs (src/pointer.rs:400-401) both say "If thePointerfails to resolve for any reason,Ok(None)is returned."Delete::deletereturnsOption<Value>and documents no panic. src/index.rs:5-7 says "attempting to use-to resolve an array value will always be out of bounds", so it should miss rather than crash. The control case/5on a 3-element array does returnNone.Root cause
src/delete.rs:108 calls
for_len_incl. That helper admitsindex == lenand mapsIndex::Nexttolen. The next line passes the result toVec::remove, which requiresindex < len.resolveuses the exclusive helperfor_lenat src/resolve.rs:293. The toml impl repeats the same call at src/delete.rs:146.Scope
Any pointer whose last token resolves to an array index equal to that array's length. That covers
-on any array and a numeric index equal to the length, including/0on an empty array. Nested arrays hit it too:/foo/-on{"foo": [1, 2]}panics. The test suite has no out-of-bounds array delete case.