diff --git a/patch.go b/patch.go index 16bcbf6..0c8f7b0 100644 --- a/patch.go +++ b/patch.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "reflect" + "strconv" "strings" ) @@ -156,6 +157,11 @@ func (v *Value) patchAdd(i int, op patchOperation) error { comp.Members[s.idx].Name.Value = String(s.name) } case *Array: + // Per RFC 6902, section 4.1, the index must not be greater + // than the number of elements in the array. + if n, err := strconv.ParseUint(s.name, 10, 0); s.name != "-" && (err != nil || n != uint64(s.idx)) { + return fmt.Errorf("hujson: patch operation %d: array index out of range: %s", i, s.name) + } insertAt(comp, s.idx, op.value) } } diff --git a/patch_test.go b/patch_test.go index 4808d6b..56d1580 100644 --- a/patch_test.go +++ b/patch_test.go @@ -179,6 +179,19 @@ var testdataPatch = []struct { in: `{"fizz":["buzz","wuzz"],"fizzy":"wizzy"}`, patch: `[{ "op": "test", "path": "/noexist", "value": null }]`, wantErr: errors.New(`hujson: patch operation 0: value not found`), +}, { + in: `[1,2]`, + patch: `[{ "op": "add", "path": "/2", "value": 3 }]`, + want: `[1,2,3]`, +}, { + in: `[1,2]`, + patch: `[{ "op": "add", "path": "/-", "value": 3 }]`, + want: `[1,2,3]`, +}, { + in: `[1,2]`, + patch: `[{ "op": "add", "path": "/5", "value": 3 }]`, + wantErr: errors.New(`hujson: patch operation 0: array index out of range: 5`), + want: `[1,2]`, }, { in: `{}`, patch: `[{`,