Merge pull request #32525 from locker95/fix/values-eof-multiple-of-buffer

fix(loader): do not drop values files ending at a 4096-byte boundary
pull/32561/head
Matt Farina 3 weeks ago committed by GitHub
commit fa9e77c0c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -183,8 +183,20 @@ func LoadFiles(files []*archive.BufferedFile) (*chart.Chart, error) {
// The reader is expected to contain one or more YAML documents, the values of which are merged.
// And the values can be either a chart's default values or user-supplied values.
func LoadValues(data io.Reader) (map[string]any, error) {
// Read fully first. YAMLReader/LineReader can drop a final unterminated
// line when its length is an exact multiple of bufio.Reader's default
// buffer (4096). Appending a trailing newline avoids that case.
// See https://github.com/helm/helm/issues/32506
b, err := io.ReadAll(data)
if err != nil {
return nil, err
}
if len(b) > 0 && b[len(b)-1] != '\n' {
b = append(b, '\n')
}
values := map[string]any{}
reader := utilyaml.NewYAMLReader(bufio.NewReader(data))
reader := utilyaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(b)))
for {
currentMap := map[string]any{}
raw, err := reader.Read()

@ -21,6 +21,7 @@ import (
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"log"
"os"
@ -419,6 +420,33 @@ foo:
}
}
func TestLoadValuesEOFBoundary(t *testing.T) {
// Reproduces #32506: a single logical line whose length is a multiple of
// bufio's default buffer (4096) and has no trailing newline used to be
// dropped entirely by YAMLReader, yielding empty values.
// Also cover 8192 (2x buffer) so we do not only hit the single-buffer case.
for _, size := range []int{4096, 8192} {
t.Run(fmt.Sprintf("size_%d", size), func(t *testing.T) {
prefix := []byte(`{"foo":"`)
suffix := []byte(`"}`)
pad := size - len(prefix) - len(suffix)
data := make([]byte, 0, size)
data = append(data, prefix...)
data = append(data, bytes.Repeat([]byte("x"), pad)...)
data = append(data, suffix...)
if len(data) != size {
t.Fatalf("test setup: want data length %d, got %d", size, len(data))
}
values, err := LoadValues(bytes.NewReader(data))
require.NoError(t, err)
assert.Equal(t, map[string]any{
"foo": string(bytes.Repeat([]byte("x"), pad)),
}, values)
})
}
}
func TestMergeValuesV3(t *testing.T) {
nestedMap := map[string]any{
"foo": "bar",

@ -210,8 +210,20 @@ func LoadFiles(files []*archive.BufferedFile) (*chart.Chart, error) {
// The reader is expected to contain one or more YAML documents, the values of which are merged.
// And the values can be either a chart's default values or user-supplied values.
func LoadValues(data io.Reader) (map[string]any, error) {
// Read fully first. YAMLReader/LineReader can drop a final unterminated
// line when its length is an exact multiple of bufio.Reader's default
// buffer (4096). Appending a trailing newline avoids that case.
// See https://github.com/helm/helm/issues/32506
b, err := io.ReadAll(data)
if err != nil {
return nil, err
}
if len(b) > 0 && b[len(b)-1] != '\n' {
b = append(b, '\n')
}
values := map[string]any{}
reader := utilyaml.NewYAMLReader(bufio.NewReader(data))
reader := utilyaml.NewYAMLReader(bufio.NewReader(bytes.NewReader(b)))
for {
currentMap := map[string]any{}
raw, err := reader.Read()

@ -21,6 +21,7 @@ import (
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"log"
"os"
@ -463,6 +464,33 @@ foo:
}
}
func TestLoadValuesEOFBoundary(t *testing.T) {
// Reproduces #32506: a single logical line whose length is a multiple of
// bufio's default buffer (4096) and has no trailing newline used to be
// dropped entirely by YAMLReader, yielding empty values.
// Also cover 8192 (2x buffer) so we do not only hit the single-buffer case.
for _, size := range []int{4096, 8192} {
t.Run(fmt.Sprintf("size_%d", size), func(t *testing.T) {
prefix := []byte(`{"foo":"`)
suffix := []byte(`"}`)
pad := size - len(prefix) - len(suffix)
data := make([]byte, 0, size)
data = append(data, prefix...)
data = append(data, bytes.Repeat([]byte("x"), pad)...)
data = append(data, suffix...)
if len(data) != size {
t.Fatalf("test setup: want data length %d, got %d", size, len(data))
}
values, err := LoadValues(bytes.NewReader(data))
require.NoError(t, err)
assert.Equal(t, map[string]any{
"foo": string(bytes.Repeat([]byte("x"), pad)),
}, values)
})
}
}
func TestMergeValuesV2(t *testing.T) {
nestedMap := map[string]any{
"foo": "bar",

Loading…
Cancel
Save