Resolves a false-positive detection of multi-doc YAML streams (#693)

Fixes #673.
This commit is contained in:
Yuki Yugui Sonoda 2023-05-04 03:37:04 +09:00 committed by GitHub
parent 9c0b362ba7
commit 868d9c6f11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 100 additions and 26 deletions

View File

@ -1406,8 +1406,6 @@ func builtinParseYAML(i *interpreter, str value) (value, error) {
}
s := sval.getGoString()
isYamlStream := strings.Contains(s, "---")
elems := []interface{}{}
d := NewYAMLToJSONDecoder(strings.NewReader(s))
for {
@ -1421,7 +1419,7 @@ func builtinParseYAML(i *interpreter, str value) (value, error) {
elems = append(elems, elem)
}
if isYamlStream {
if d.IsStream() {
return jsonToValue(i, elems)
}
return jsonToValue(i, elems[0])

View File

@ -1,10 +1,41 @@
{
"aaa": { },
"foo": "bar",
"xxx": [
42,
"asdf",
{ }
[
{
"aaa": { },
"foo": "bar",
"xxx": [
42,
"asdf",
{ }
],
"ąę": "ćż"
},
[
{
"a": 1
},
{
"a": 2
}
],
"ąę": "ćż"
}
[
{
"a": 1
},
{
"a": 2
}
],
[
{
"a": 1
},
{
"a": 2
}
],
{
"---a": 2,
"a": 1,
"a---": 3
}
]

View File

@ -1,11 +1,46 @@
std.parseYaml(
|||
foo: bar
aaa: {}
ąę: ćż
xxx:
- 42
- asdf
- {}
|||
)
[
std.parseYaml(text)
for text in [
// various node types
|||
foo: bar
aaa: {}
ąę: ćż
xxx:
- 42
- asdf
- {}
|||,
// Returns an array of documents when there is an explicit document(s), i.e.
// the text is a "multi-doc" stream
|||
---
a: 1
---
a: 2
|||,
// The first document in a "multi-doc" stream can be an implicit document.
|||
a: 1
---
a: 2
|||,
// Whitespaces are allowed after the document start marker
|||
---
a: 1
---
a: 2
|||,
// Document start marker needs a following line break or a whitespace.
|||
a: 1
---a: 2
a---: 3
|||,
]
]

16
yaml.go
View File

@ -32,7 +32,7 @@ const separator = "---"
// separating individual documents. It first converts the YAML
// body to JSON, then unmarshals the JSON.
type YAMLToJSONDecoder struct {
reader Reader
reader *YAMLReader
}
// NewYAMLToJSONDecoder decodes YAML documents from the provided
@ -50,7 +50,7 @@ func NewYAMLToJSONDecoder(r io.Reader) *YAMLToJSONDecoder {
// an error. The decoding rules match json.Unmarshal, not
// yaml.Unmarshal.
func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
bytes, err := d.reader.Read()
bytes, err := d.reader.read()
if err != nil && err != io.EOF {
return err
}
@ -64,6 +64,10 @@ func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
return err
}
func (d *YAMLToJSONDecoder) IsStream() bool {
return d.reader.isStream()
}
// Reader reads bytes
type Reader interface {
Read() ([]byte, error)
@ -72,6 +76,7 @@ type Reader interface {
// YAMLReader reads YAML
type YAMLReader struct {
reader Reader
stream bool
}
// NewYAMLReader creates a new YAMLReader
@ -82,7 +87,7 @@ func NewYAMLReader(r *bufio.Reader) *YAMLReader {
}
// Read returns a full YAML document.
func (r *YAMLReader) Read() ([]byte, error) {
func (r *YAMLReader) read() ([]byte, error) {
var buffer bytes.Buffer
for {
line, err := r.reader.Read()
@ -96,6 +101,7 @@ func (r *YAMLReader) Read() ([]byte, error) {
i += sep
after := line[i:]
if len(strings.TrimRightFunc(string(after), unicode.IsSpace)) == 0 {
r.stream = true
if buffer.Len() != 0 {
return buffer.Bytes(), nil
}
@ -115,6 +121,10 @@ func (r *YAMLReader) Read() ([]byte, error) {
}
}
func (r *YAMLReader) isStream() bool {
return r.stream
}
// LineReader reads single lines.
type LineReader struct {
reader *bufio.Reader