fix(kyaml/yaml): minor nil safety fix for RNode.Content etc (#5985)

* Fix kyaml/yaml field access deref nil value for methods that look "nil-safe"

This change is addressing observed panics within kustomize that obscure the
actual failure. The primary observed problem case involves RNode.Content.

* Fix test case

* Fixes from review
This commit is contained in:
Joseph Cumines
2025-11-03 12:34:07 +10:00
committed by GitHub
parent 153a37286d
commit 87617912bf
2 changed files with 92 additions and 6 deletions

View File

@@ -718,10 +718,11 @@ func (rn *RNode) MustString() string {
// Content returns Node Content field.
func (rn *RNode) Content() []*yaml.Node {
if rn == nil {
yNode := rn.YNode()
if yNode == nil {
return nil
}
return rn.YNode().Content
return yNode.Content
}
// Fields returns the list of field names for a MappingNode.
@@ -756,7 +757,11 @@ func (rn *RNode) FieldRNodes() ([]*RNode, error) {
// Field returns a fieldName, fieldValue pair for MappingNodes.
// Returns nil for non-MappingNodes.
func (rn *RNode) Field(field string) *MapNode {
if rn.YNode().Kind != yaml.MappingNode {
yNode := rn.YNode()
if yNode == nil {
return nil
}
if yNode.Kind != yaml.MappingNode {
return nil
}
var result *MapNode
@@ -892,7 +897,11 @@ func (rn *RNode) ElementValuesList(keys []string) ([][]string, error) {
// Element returns the element in the list which contains the field matching the value.
// Returns nil for non-SequenceNodes or if no Element matches.
func (rn *RNode) Element(key, value string) *RNode {
if rn.YNode().Kind != yaml.SequenceNode {
yNode := rn.YNode()
if yNode == nil {
return nil
}
if yNode.Kind != yaml.SequenceNode {
return nil
}
elem, err := rn.Pipe(MatchElement(key, value))
@@ -906,7 +915,11 @@ func (rn *RNode) Element(key, value string) *RNode {
// corresponding values[i].
// Returns nil for non-SequenceNodes or if no Element matches.
func (rn *RNode) ElementList(keys []string, values []string) *RNode {
if rn.YNode().Kind != yaml.SequenceNode {
yNode := rn.YNode()
if yNode == nil {
return nil
}
if yNode.Kind != yaml.SequenceNode {
return nil
}
elem, err := rn.Pipe(MatchElementList(keys, values))
@@ -960,12 +973,17 @@ func (rn *RNode) GetAssociativeKey() string {
// MarshalJSON creates a byte slice from the RNode.
func (rn *RNode) MarshalJSON() ([]byte, error) {
yNode := rn.YNode()
if yNode == nil {
return []byte("null"), nil
}
s, err := rn.String()
if err != nil {
return nil, err
}
if rn.YNode().Kind == SequenceNode {
if yNode.Kind == SequenceNode {
var a []interface{}
if err := Unmarshal([]byte(s), &a); err != nil {
return nil, err
@@ -977,6 +995,7 @@ func (rn *RNode) MarshalJSON() ([]byte, error) {
if err := Unmarshal([]byte(s), &m); err != nil {
return nil, err
}
return json.Marshal(m)
}