fix(encode): reject a nil MarshalTOML result

Assisted-by: GLM 5.3
This commit is contained in:
2026-09-17 23:11:10 +02:00
parent d5327568fb
commit 4def1b3e8b
4 changed files with 61 additions and 2 deletions
+20 -1
View File
@@ -300,6 +300,12 @@ func buildMapDoc(v reflect.Value, doc *tomlDoc, ctx string) error {
// --- reflection walk: field dispatch -------------------------------------
// errNilMarshalTOML reports a Marshaler whose method returned a nil value
// with no error. nil has no TOML representation, so dropping the field
// silently or panicking on the invalid reflect.Value would both hide the
// contract violation.
var errNilMarshalTOML = errors.New("MarshalTOML returned a nil value")
func addField(doc *tomlDoc, name string, v reflect.Value, ctx string) error {
if v.CanInterface() {
if m, ok := v.Interface().(Marshaler); ok {
@@ -307,6 +313,9 @@ func addField(doc *tomlDoc, name string, v reflect.Value, ctx string) error {
if err != nil {
return &EncodeError{Path: joinKey(ctx, name), Err: err}
}
if mv == nil {
return &EncodeError{Path: joinKey(ctx, name), Err: errNilMarshalTOML}
}
v = reflect.ValueOf(mv)
}
}
@@ -448,6 +457,9 @@ func addArrayValue(doc *tomlDoc, name string, v reflect.Value, ctx string) error
if err != nil {
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: err}
}
if mv == nil {
return &EncodeError{Path: fmt.Sprintf("%s[%d]", joinKey(ctx, name), i), Err: errNilMarshalTOML}
}
ev = reflect.ValueOf(mv)
ev = followPtr(ev)
}
@@ -474,7 +486,14 @@ func normaliseValue(v reflect.Value) (any, error) {
}
if v.CanInterface() {
if m, ok := v.Interface().(Marshaler); ok {
return m.MarshalTOML()
mv, err := m.MarshalTOML()
if err != nil {
return nil, err
}
if mv == nil {
return nil, errNilMarshalTOML
}
return mv, nil
}
}
// The datetime structs are TOML scalars; the emitter renders each of them.