Skip to content

Panic when converting a struct that embeds a pointer to another struct to Unstructured  #172

@christarazi

Description

@christarazi

The following setup can lead to a panic. The issue seems to be with embedding a pointer to a struct, when using runtime.DefaultUnstructuredConverter.ToUnstructured.

type A struct {
  *B `json:",inline"`
}

type B struct {
  Foo string `json:"foo"`
}

The panic observed is:

... Panic: reflect: NumField of non-struct type *v2.CiliumNetworkPolicy (PC=0x46A7A8)

/usr/lib/go/src/runtime/panic.go:975
  in gopanic
/usr/lib/go/src/reflect/type.go:974
  in rtype.NumField
/home/chris/code/cilium/cilium/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go:146
  in buildStructCacheEntry
/home/chris/code/cilium/cilium/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go:153
  in buildStructCacheEntry
/home/chris/code/cilium/cilium/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go:119
  in typeReflectEntryOf
/home/chris/code/cilium/cilium/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go:94
  in TypeReflectEntryOf
/home/chris/code/cilium/cilium/vendor/k8s.io/apimachinery/pkg/runtime/converter.go:480
  in toUnstructured
/home/chris/code/cilium/cilium/vendor/k8s.io/apimachinery/pkg/runtime/converter.go:413
  in unstructuredConverter.ToUnstructured
unknown_fields.go:102
  in detectUnknownFields
validator.go:138
  in NPValidator.ValidateCCNP
validator_test.go:189
  in CNPValidationSuite.Test_GoodCCNP
/usr/lib/go/src/reflect/value.go:336
  in Value.Call
/usr/lib/go/src/runtime/asm_amd64.s:1374
  in goexit

The following patch fixes the issue:

diff --git a/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go b/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go
index 49e6dd169..ff16bd52f 100644
--- a/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go
+++ b/vendor/sigs.k8s.io/structured-merge-diff/v4/value/reflectcache.go
@@ -150,7 +150,11 @@ func buildStructCacheEntry(t reflect.Type, infos map[string]*FieldCacheEntry, fi
 			continue
 		}
 		if isInline {
-			buildStructCacheEntry(field.Type, infos, append(fieldPath, field.Index))
+			e := field.Type
+			if field.Type.Kind() == reflect.Ptr {
+				e = field.Type.Elem()
+			}
+			buildStructCacheEntry(e, infos, append(fieldPath, field.Index))
 			continue
 		}
 		info := &FieldCacheEntry{JsonName: jsonName, isOmitEmpty: isOmitempty, fieldPath: append(fieldPath, field.Index), fieldType: field.Type}

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.priority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next release.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions