diff --git a/pkg/yqlib/decoder_base64.go b/pkg/yqlib/decoder_base64.go index c4868fd2..f1cace87 100644 --- a/pkg/yqlib/decoder_base64.go +++ b/pkg/yqlib/decoder_base64.go @@ -4,10 +4,33 @@ import ( "bytes" "encoding/base64" "io" + "strings" yaml "gopkg.in/yaml.v3" ) +type base64Padder struct { + count uint64 + io.Reader +} + +func (c *base64Padder) pad(buf []byte) (int, error) { + pad := strings.Repeat("=", int(4-c.count%4)) + n, err := strings.NewReader(pad).Read(buf) + c.count += uint64(n) + return n, err +} + +func (c *base64Padder) Read(buf []byte) (int, error) { + n, err := c.Reader.Read(buf) + c.count += uint64(n) + + if err == io.EOF && c.count%4 != 0 { + return c.pad(buf) + } + return n, err +} + type base64Decoder struct { reader io.Reader finished bool @@ -20,7 +43,7 @@ func NewBase64Decoder() Decoder { } func (dec *base64Decoder) Init(reader io.Reader) error { - dec.reader = reader + dec.reader = &base64Padder{Reader: reader} dec.readAnything = false dec.finished = false return nil diff --git a/pkg/yqlib/operator_encoder_decoder_test.go b/pkg/yqlib/operator_encoder_decoder_test.go index 83b3023c..381d56df 100644 --- a/pkg/yqlib/operator_encoder_decoder_test.go +++ b/pkg/yqlib/operator_encoder_decoder_test.go @@ -310,6 +310,14 @@ var encoderDecoderOperatorScenarios = []expressionScenario{ "D0, P[], (!!str)::\n", }, }, + { + description: "base64 missing padding test", + skipDoc: true, + expression: `"Y2F0cw" | @base64d`, + expected: []string{ + "D0, P[], (!!str)::cats\n", + }, + }, { requiresFormat: "xml", description: "empty xml decode",