Skip to content

Delete on a JSON array panics when the index equals the array length #120

Description

@hey-jj

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions