Skip to content

Commit 1cab325

Browse files
committed
vcsim: Fix RetrieveProperties path validation to avoid panic
Closes: #2953 Signed-off-by: syuparn <[email protected]>
1 parent 25a83f0 commit 1cab325

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

simulator/property_collector.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func NewPropertyCollector(ref types.ManagedObjectReference) object.Reference {
5252

5353
var errMissingField = errors.New("missing field")
5454
var errEmptyField = errors.New("empty field")
55+
var errInvalidField = errors.New("invalid field")
5556

5657
func getObject(ctx *Context, ref types.ManagedObjectReference) (reflect.Value, bool) {
5758
var obj mo.Reference
@@ -180,6 +181,11 @@ func fieldValue(rval reflect.Value, p string) (interface{}, error) {
180181
rval = rval.Elem()
181182
}
182183

184+
if kind == reflect.Slice {
185+
// field of array field cannot be specified
186+
return nil, errInvalidField
187+
}
188+
183189
x := ucFirst(name)
184190
val := rval.FieldByName(x)
185191
if !val.IsValid() {
@@ -316,6 +322,13 @@ func (rr *retrieveResult) collectFields(ctx *Context, rval reflect.Value, fields
316322
Name: name,
317323
}},
318324
})
325+
case errInvalidField:
326+
content.MissingSet = append(content.MissingSet, types.MissingProperty{
327+
Path: name,
328+
Fault: types.LocalizedMethodFault{Fault: &types.InvalidProperty{
329+
Name: name,
330+
}},
331+
})
319332
}
320333
}
321334
}

simulator/property_collector_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/vmware/govmomi/simulator/esx"
3232
"github.com/vmware/govmomi/simulator/vpx"
3333
"github.com/vmware/govmomi/view"
34+
"github.com/vmware/govmomi/vim25"
3435
"github.com/vmware/govmomi/vim25/methods"
3536
"github.com/vmware/govmomi/vim25/mo"
3637
"github.com/vmware/govmomi/vim25/soap"
@@ -846,6 +847,53 @@ func TestPropertyCollectorInvalidSpecName(t *testing.T) {
846847
}
847848
}
848849

850+
func TestPropertyCollectorInvalidProperty(t *testing.T) {
851+
tests := []struct {
852+
name string
853+
path string
854+
expectedFault types.BaseMethodFault
855+
}{
856+
{
857+
"specify property of array property",
858+
"config.hardware.device.key",
859+
new(types.InvalidProperty),
860+
},
861+
}
862+
863+
for _, test := range tests {
864+
test := test // assign to local var since loop var is reused
865+
866+
t.Run(test.name, func(t *testing.T) {
867+
m := ESX()
868+
869+
Test(func(ctx context.Context, c *vim25.Client) {
870+
pc := property.DefaultCollector(c)
871+
872+
vm := Map.Any("VirtualMachine")
873+
vmRef := vm.Reference()
874+
875+
var vmMo mo.VirtualMachine
876+
err := pc.RetrieveOne(ctx, vmRef, []string{test.path}, &vmMo)
877+
if err == nil {
878+
t.Fatal("expected error")
879+
}
880+
881+
// NOTE: since soap.vimFaultError is not exported, use interface literal for assertion instead
882+
fault, ok := err.(interface {
883+
Fault() types.BaseMethodFault
884+
})
885+
if !ok {
886+
t.Fatalf("err does not have fault: type: %T", err)
887+
}
888+
889+
if reflect.TypeOf(fault.Fault()) != reflect.TypeOf(test.expectedFault) {
890+
t.Errorf("expected fault: %T, actual fault: %T", test.expectedFault, fault.Fault())
891+
}
892+
}, m)
893+
})
894+
}
895+
}
896+
849897
func TestPropertyCollectorRecursiveSelectSet(t *testing.T) {
850898
ctx := context.Background()
851899

0 commit comments

Comments
 (0)