Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: prevent panic on depinject when input or output struct has an un… #12786

Merged
54 changes: 54 additions & 0 deletions depinject/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ type KeeperB struct {
msgClientA MsgClientA
}

type KeeperC struct {
key KVStoreKey
msgClientA MsgClientA
}

type Handler struct {
Handle func()
}
Expand Down Expand Up @@ -58,6 +63,8 @@ func (ModuleA) Provide(key KVStoreKey, moduleKey depinject.OwnModuleKey) (Keeper

type ModuleB struct{}

type ModuleC struct{}

type BDependencies struct {
depinject.In

Expand All @@ -82,6 +89,53 @@ func (ModuleB) Provide(dependencies BDependencies) (BProvides, Handler, error) {
}, Handler{}, nil
}

type UnexportedFieldCDependencies struct {
depinject.In

key KVStoreKey
A MsgClientA
}

type UnexportedFieldCProvides struct {
depinject.Out

keeperC KeeperC
Commands []Command
}

func (ModuleC) Provide(dependencies BDependencies) (UnexportedFieldCProvides, Handler, error) {
return UnexportedFieldCProvides{
keeperC: KeeperC{
key: dependencies.Key,
msgClientA: dependencies.A,
},
Commands: []Command{{}, {}},
}, Handler{}, nil
}

func TestUnexportedField(t *testing.T) {
var (
handlers map[string]Handler
commands []Command
a KeeperA
b KeeperB

scenarioConfig = depinject.Configs(
depinject.ProvideInModule("a", wrapMethod0(ModuleA{})),
depinject.ProvideInModule("b", wrapMethod0(ModuleC{})),
)
)

require.Error(t,
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
depinject.Inject(
scenarioConfig,
&handlers,
&commands,
&a,
&b,
))
}

var scenarioConfig = depinject.Configs(
depinject.Provide(ProvideMsgClientA),
depinject.ProvideInModule("runtime", ProvideKVStoreKey),
Expand Down
13 changes: 10 additions & 3 deletions depinject/struct_args.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package depinject

import (
"fmt"
"reflect"

"github.com/pkg/errors"
Expand Down Expand Up @@ -74,7 +75,10 @@ func expandStructArgsFn(provider ProviderDescriptor) func(inputs []reflect.Value
inputs1 := make([]reflect.Value, len(inParams))
for i, in := range inParams {
if in.Type.AssignableTo(isInType) {
v, n := buildIn(in.Type, inputs[j:])
v, n, err := buildIn(in.Type, inputs[j:])
if err != nil {
return []reflect.Value{}, err
}
inputs1[i] = v
j += n
} else {
Expand Down Expand Up @@ -158,7 +162,7 @@ func structArgsOutTypes(typ reflect.Type) []ProviderOutput {
return res
}

func buildIn(typ reflect.Type, values []reflect.Value) (reflect.Value, int) {
func buildIn(typ reflect.Type, values []reflect.Value) (reflect.Value, int, error) {
numFields := typ.NumField()
j := 0
res := reflect.New(typ)
Expand All @@ -167,11 +171,14 @@ func buildIn(typ reflect.Type, values []reflect.Value) (reflect.Value, int) {
if f.Type.AssignableTo(isInType) {
continue
}
if !res.Elem().Field(i).CanSet() {
return reflect.Value{}, 0, fmt.Errorf("using value obtained using unexported field %s from %s on package %s", f.Name, res.Elem().String(), f.PkgPath)
JeancarloBarrios marked this conversation as resolved.
Show resolved Hide resolved
}

res.Elem().Field(i).Set(values[j])
j++
}
return res.Elem(), j
return res.Elem(), j, nil
}

func extractFromOut(typ reflect.Type, value reflect.Value) []reflect.Value {
Expand Down