mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
Merge pull request #123620 from benluddy/json-frame-reader-underlying-array-reuse
Remove shared ref to underlying array of JSONFrameReader's Read arg.
This commit is contained in:
commit
5cb71ec2e4
@ -147,7 +147,6 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
|
|||||||
|
|
||||||
// RawMessage#Unmarshal appends to data - we reset the slice down to 0 and will either see
|
// RawMessage#Unmarshal appends to data - we reset the slice down to 0 and will either see
|
||||||
// data written to data, or be larger than data and a different array.
|
// data written to data, or be larger than data and a different array.
|
||||||
n := len(data)
|
|
||||||
m := json.RawMessage(data[:0])
|
m := json.RawMessage(data[:0])
|
||||||
if err := r.decoder.Decode(&m); err != nil {
|
if err := r.decoder.Decode(&m); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -156,12 +155,19 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
|
|||||||
// If capacity of data is less than length of the message, decoder will allocate a new slice
|
// If capacity of data is less than length of the message, decoder will allocate a new slice
|
||||||
// and set m to it, which means we need to copy the partial result back into data and preserve
|
// and set m to it, which means we need to copy the partial result back into data and preserve
|
||||||
// the remaining result for subsequent reads.
|
// the remaining result for subsequent reads.
|
||||||
if len(m) > n {
|
if len(m) > cap(data) {
|
||||||
//nolint:staticcheck // SA4006,SA4010 underlying array of data is modified here.
|
copy(data, m)
|
||||||
data = append(data[0:0], m[:n]...)
|
r.remaining = m[len(data):]
|
||||||
r.remaining = m[n:]
|
return len(data), io.ErrShortBuffer
|
||||||
return n, io.ErrShortBuffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(m) > len(data) {
|
||||||
|
// The bytes beyond len(data) were stored in data's underlying array, which we do
|
||||||
|
// not own after this function returns.
|
||||||
|
r.remaining = append([]byte(nil), m[len(data):]...)
|
||||||
|
return len(data), io.ErrShortBuffer
|
||||||
|
}
|
||||||
|
|
||||||
return len(m), nil
|
return len(m), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package framer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -173,3 +174,17 @@ func TestJSONFrameReaderShortBuffer(t *testing.T) {
|
|||||||
t.Fatalf("unexpected: %v %d %q", err, n, buf)
|
t.Fatalf("unexpected: %v %d %q", err, n, buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJSONFrameReaderShortBufferNoUnderlyingArrayReuse(t *testing.T) {
|
||||||
|
b := bytes.NewBufferString("{}")
|
||||||
|
r := NewJSONFramedReader(io.NopCloser(b))
|
||||||
|
buf := make([]byte, 1, 2) // cap(buf) > len(buf) && cap(buf) <= len("{}")
|
||||||
|
|
||||||
|
if n, err := r.Read(buf); !errors.Is(err, io.ErrShortBuffer) || n != 1 || string(buf[:n]) != "{" {
|
||||||
|
t.Fatalf("unexpected: %v %d %q", err, n, buf)
|
||||||
|
}
|
||||||
|
buf = append(buf, make([]byte, 1)...) // stomps the second byte of the backing array
|
||||||
|
if n, err := r.Read(buf[1:]); err != nil || n != 1 || string(buf[1:1+n]) != "}" {
|
||||||
|
t.Fatalf("unexpected: %v %d %q", err, n, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user