diff --git a/expand.go b/expand.go index 2ad692d..49245fa 100644 --- a/expand.go +++ b/expand.go @@ -23,7 +23,6 @@ package config import ( "bytes" "fmt" - "io/ioutil" "strings" "golang.org/x/text/transform" @@ -43,7 +42,10 @@ func expandVariables(f LookupFunc, buf *bytes.Buffer) (*bytes.Buffer, error) { if f == nil { return buf, nil } - exp, err := ioutil.ReadAll(transform.NewReader(buf, newExpandTransformer(f))) + // when a single ${VAR} expands to a string larger than the reader's fixed dst buffer, + // transform.Bytes will grow the dst buffer automatically, unlike f.e. + // transform.NewReader + ReadAll, which will return ErrShortDst. + exp, _, err := transform.Bytes(newExpandTransformer(f), buf.Bytes()) if err != nil { return nil, fmt.Errorf("couldn't expand environment: %v", err) } diff --git a/expand_test.go b/expand_test.go index d809c57..7092011 100644 --- a/expand_test.go +++ b/expand_test.go @@ -238,6 +238,22 @@ func TestExpanderLongSrc(t *testing.T) { } } +func TestExpandVariablesLargeReplacement(t *testing.T) { + // Regression: transform.Reader fails with ErrShortDst when the replacement + // is larger than transform's internal destination buffer and sits at the + // start of the input (Reader requires nDst!=0 || nSrc!=0 to retry). + output := strings.Repeat("a", transformBufSize-1) + "aa" + lookup := func(key string) (string, bool) { + if key == "a" { + return output, true + } + return "", false + } + out, err := expandVariables(lookup, bytes.NewBufferString("$a")) + require.NoError(t, err) + assert.Equal(t, output, out.String()) +} + func TestTransformLimit(t *testing.T) { a := strings.Repeat("a", transformBufSize-1)