diff --git a/internal/protohcl/primitives.go b/internal/protohcl/primitives.go index 4d1f220330..c93218c997 100644 --- a/internal/protohcl/primitives.go +++ b/internal/protohcl/primitives.go @@ -63,14 +63,20 @@ func protoEnumFromCty(desc protoreflect.FieldDescriptor, val cty.Value) (protore } if val.IsNull() { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + if desc.HasDefault() { + defaultValDesc := desc.DefaultEnumValue() + return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + } + return protoreflect.Value{}, fmt.Errorf("no default value for type and value is null") } valDesc := desc.Enum().Values().ByName(protoreflect.Name(val.AsString())) if valDesc == nil { - defaultValDesc := desc.DefaultEnumValue() - return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + if desc.HasDefault() { + defaultValDesc := desc.DefaultEnumValue() + return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil + } + return protoreflect.Value{}, fmt.Errorf("no default value for type and value is invalid") } return protoreflect.ValueOfEnum(valDesc.Number()), nil diff --git a/internal/resourcehcl/any.go b/internal/resourcehcl/any.go index 3d797c48e5..71086f655d 100644 --- a/internal/resourcehcl/any.go +++ b/internal/resourcehcl/any.go @@ -34,12 +34,15 @@ func (p anyProvider) AnyType(ctx *protohcl.UnmarshalContext, decoder protohcl.Me if !isResource { return p.base.AnyType(ctx, decoder) } - - resourceType := res.GetId().GetType() if res == nil { return "", nil, errors.New("ID.Type not found") } + resourceType := res.GetId().GetType() + if resourceType == nil { + return "", nil, errors.New("ID.Type is nil") + } + reg, ok := p.reg.Resolve(resourceType) if !ok { return "", nil, fmt.Errorf("unknown resource type: %s", resource.ToGVK(resourceType)) diff --git a/internal/resourcehcl/naming.go b/internal/resourcehcl/naming.go index a1160cc323..590ea06788 100644 --- a/internal/resourcehcl/naming.go +++ b/internal/resourcehcl/naming.go @@ -33,6 +33,9 @@ func (n fieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) pro } } + if len(name) <= 1 { + return fds.ByJSONName(name) + } camel := strings.ToLower(name[:1]) + name[1:] return fds.ByJSONName(camel) } diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc new file mode 100644 index 0000000000..7f8a2357c7 --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/0e4b8ec300611dbc @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("Data{}") diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 new file mode 100644 index 0000000000..3d99674458 --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/c800420b7494c6d1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("ID={\"\"=\"\"}") diff --git a/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 new file mode 100644 index 0000000000..b63214c55a --- /dev/null +++ b/internal/resourcehcl/testdata/fuzz/FuzzUnmarshall/eaba8205942c3f31 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("ID {\nType = gvk(\"demo.v1.Artist\")\n} \nData {\nGenre = \"\"\n} ") diff --git a/internal/resourcehcl/unmarshal_test.go b/internal/resourcehcl/unmarshal_test.go index 5e35f7df66..e5b6506744 100644 --- a/internal/resourcehcl/unmarshal_test.go +++ b/internal/resourcehcl/unmarshal_test.go @@ -23,6 +23,47 @@ import ( var update = flag.Bool("update", false, "update golden files") +func FuzzUnmarshall(f *testing.F) { + entries, err := os.ReadDir("./testdata") + require.NoError(f, err) + + read := func(t *testing.F, path string) ([]byte, bool) { + t.Helper() + + bytes, err := os.ReadFile(fmt.Sprintf("./testdata/%s", path)) + switch { + case err == nil: + return bytes, true + case os.IsNotExist(err): + return nil, false + } + + t.Fatalf("failed to read file %s %v", path, err) + return nil, false + } + for _, entry := range entries { + ext := path.Ext(entry.Name()) + + if ext != ".hcl" { + continue + } + input, _ := read(f, entry.Name()) + f.Add(input) + } + registry := resource.NewRegistry() + demo.RegisterTypes(registry) + mesh.RegisterTypes(registry) + + f.Fuzz(func(t *testing.T, input []byte) { + got, err := resourcehcl.Unmarshal(input, registry) + if err != nil { + return + } + require.NotNil(t, got) + }) + +} + func TestUnmarshal(t *testing.T) { entries, err := os.ReadDir("./testdata") require.NoError(t, err)