Skip to content

Panic in TypeReflectCacheEntry.ToUnstructured if a pointer-typed field without omitempty specifier is attempted to be converted #229

Closed as not planned
@ulucinar

Description

@ulucinar

Hello,
We have observed in Crossplane project's CNCF fuzzing tests that runtime.DefaultUnstructuredConverter.ToUnstructured (from k8s.io/[email protected]) consuming sigs.k8s.io/structured-merge-diff/[email protected] panics with the following sample program:

package main

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

type Test struct {
	Time *metav1.Time
}

func main() {
	if _, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&Test{}); err != nil {
		panic(err)
	}
}

, producing the following stacktrace:

panic: value method k8s.io/apimachinery/pkg/apis/meta/v1.Time.ToUnstructured called using nil *Time pointer

goroutine 1 [running]:
k8s.io/apimachinery/pkg/apis/meta/v1.(*Time).ToUnstructured(0x100000001?)
        <autogenerated>:1 +0x48
sigs.k8s.io/structured-merge-diff/v4/value.TypeReflectCacheEntry.ToUnstructured({0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, {0x0, 0x0, 0x0}}, ...)
        /Users/alper/data/workspaces/go/pkg/mod/sigs.k8s.io/structured-merge-diff/[email protected]/value/reflectcache.go:188 +0x6b0
k8s.io/apimachinery/pkg/runtime.toUnstructured({0x100f7cba0?, 0x140001aa3d0?, 0x0?}, {0x100efef60?, 0x14000193f10?, 0x0?})
        /Users/alper/data/workspaces/go/pkg/mod/k8s.io/[email protected]/pkg/runtime/converter.go:655 +0x8a0
k8s.io/apimachinery/pkg/runtime.structToUnstructured({0x100f1f260?, 0x140001aa3d0?, 0x100f7f5e0?}, {0x100f0a3c0?, 0x140001aa3d8?, 0x100a61548?})
        /Users/alper/data/workspaces/go/pkg/mod/k8s.io/[email protected]/pkg/runtime/converter.go:843 +0x7ac
k8s.io/apimachinery/pkg/runtime.toUnstructured({0x100f1f260?, 0x140001aa3d0?, 0x140001aa3d0?}, {0x100f0a3c0?, 0x140001aa3d8?, 0x140000021a0?})
        /Users/alper/data/workspaces/go/pkg/mod/k8s.io/[email protected]/pkg/runtime/converter.go:692 +0x7f4
k8s.io/apimachinery/pkg/runtime.(*unstructuredConverter).ToUnstructured(0x101277530, {0x100edca80?, 0x140001aa3d0})
        /Users/alper/data/workspaces/go/pkg/mod/k8s.io/[email protected]/pkg/runtime/converter.go:586 +0x364
main.main()
        /Users/alper/data/workspaces/github.com/ulucinar/crossplane/crossplane/cmd/test/main.go:13 +0x44

The same behavior is observed also with k8s.io/[email protected], which depends on sigs.k8s.io/structured-merge-diff/[email protected].

As a workaround, if a json tag is added with the omitempty specifier, then no panic is observed:

package main

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

type Test struct {
	Time *metav1.Time `json:"time,omitempty"`
}

func main() {
	if _, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&Test{}); err != nil {
		panic(err)
	}
}

As the stacktrace points, it looks like we are calling converter.ToUnstructured with a nil converter here.

Would adding a nil check for the converter variable there be appropriate (and maybe returning a nil, nil so that we do not attempt to convert a nil value, or return an error)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    lifecycle/rottenDenotes an issue or PR that has aged beyond stale and will be auto-closed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions