Merge pull request #74102 from caesarxuchao/automated-cherry-pick-of-#73443-#73713-#73805-#74000-upstream-release-1.13

Automated cherry pick of #73443: update json-patch to pick up bug fixes

Kubernetes-commit: de4225fa13bfb50581f80e6af63b326a3c1028b1
This commit is contained in:
Kubernetes Publisher
2019-02-21 12:46:51 -08:00
parent a5274af388
commit 9593044ffe
13 changed files with 480 additions and 306 deletions
+66 -36
View File
@@ -14,6 +14,16 @@ const (
eAry
)
var (
// SupportNegativeIndices decides whether to support non-standard practice of
// allowing negative indices to mean indices starting at the end of an array.
// Default to true.
SupportNegativeIndices bool = true
// AccumulatedCopySizeLimit limits the total size increase in bytes caused by
// "copy" operations in a patch.
AccumulatedCopySizeLimit int64 = 0
)
type lazyNode struct {
raw *json.RawMessage
doc partialDoc
@@ -61,6 +71,20 @@ func (n *lazyNode) UnmarshalJSON(data []byte) error {
return nil
}
func deepCopy(src *lazyNode) (*lazyNode, int, error) {
if src == nil {
return nil, 0, nil
}
a, err := src.MarshalJSON()
if err != nil {
return nil, 0, err
}
sz := len(a)
ra := make(json.RawMessage, sz)
copy(ra, a)
return newLazyNode(&ra), sz, nil
}
func (n *lazyNode) intoDoc() (*partialDoc, error) {
if n.which == eDoc {
return &n.doc, nil
@@ -342,35 +366,14 @@ func (d *partialDoc) remove(key string) error {
return nil
}
// set should only be used to implement the "replace" operation, so "key" must
// be an already existing index in "d".
func (d *partialArray) set(key string, val *lazyNode) error {
if key == "-" {
*d = append(*d, val)
return nil
}
idx, err := strconv.Atoi(key)
if err != nil {
return err
}
sz := len(*d)
if idx+1 > sz {
sz = idx + 1
}
ary := make([]*lazyNode, sz)
cur := *d
copy(ary, cur)
if idx >= len(ary) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
ary[idx] = val
*d = ary
(*d)[idx] = val
return nil
}
@@ -385,17 +388,26 @@ func (d *partialArray) add(key string, val *lazyNode) error {
return err
}
ary := make([]*lazyNode, len(*d)+1)
sz := len(*d) + 1
ary := make([]*lazyNode, sz)
cur := *d
if idx < -len(ary) || idx >= len(ary) {
if idx >= len(ary) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(ary)
if SupportNegativeIndices {
if idx < -len(ary) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(ary)
}
}
copy(ary[0:idx], cur[0:idx])
ary[idx] = val
copy(ary[idx+1:], cur[idx:])
@@ -426,11 +438,18 @@ func (d *partialArray) remove(key string) error {
cur := *d
if idx < -len(cur) || idx >= len(cur) {
return fmt.Errorf("Unable to remove invalid index: %d", idx)
if idx >= len(cur) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(cur)
if SupportNegativeIndices {
if idx < -len(cur) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(cur)
}
}
ary := make([]*lazyNode, len(cur)-1)
@@ -511,7 +530,7 @@ func (p Patch) move(doc *container, op operation) error {
return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path)
}
return con.set(key, val)
return con.add(key, val)
}
func (p Patch) test(doc *container, op operation) error {
@@ -545,7 +564,7 @@ func (p Patch) test(doc *container, op operation) error {
return fmt.Errorf("Testing value %s failed", path)
}
func (p Patch) copy(doc *container, op operation) error {
func (p Patch) copy(doc *container, op operation, accumulatedCopySize *int64) error {
from := op.from()
con, key := findObject(doc, from)
@@ -567,7 +586,16 @@ func (p Patch) copy(doc *container, op operation) error {
return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path)
}
return con.set(key, val)
valCopy, sz, err := deepCopy(val)
if err != nil {
return err
}
(*accumulatedCopySize) += int64(sz)
if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit {
return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize)
}
return con.add(key, valCopy)
}
// Equal indicates if 2 JSON documents have the same structural equality.
@@ -620,6 +648,8 @@ func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
err = nil
var accumulatedCopySize int64
for _, op := range p {
switch op.kind() {
case "add":
@@ -633,7 +663,7 @@ func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
case "test":
err = p.test(&pd, op)
case "copy":
err = p.copy(&pd, op)
err = p.copy(&pd, op, &accumulatedCopySize)
default:
err = fmt.Errorf("Unexpected kind: %s", op.kind())
}