Skip to content

Commit

Permalink
Fixed issue where Unmarshal crashes when given an unsettable variable.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisTrenkamp committed Dec 26, 2023
1 parent d5cab23 commit 65728c1
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
26 changes: 26 additions & 0 deletions exec/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,32 @@ func TestHtmlDocument(t *testing.T) {
}
}

func TestNonPointerSliceUnmarshal(t *testing.T) {
sl := make([]int, 0)
xml := `
<root>
<elem>1</elem>
<elem>2</elem>
<elem>3</elem>
</root>
`

nodes := execXmlNodes(t, "/root/elem", xml)
err := Unmarshal(nodes, sl)
if err.Error() != "field <slice> is not settable" {
t.Error("incorrect error:", err)
}

err = Unmarshal(nodes, &sl)
if err != nil {
t.Error("got error:", err)
}

if !reflect.DeepEqual(sl, []int{1, 2, 3}) {
t.Error("incorrect result:", sl)
}
}

func TestUnmarshal(t *testing.T) {
type SubUnmarshalTarget struct {
A *string `xsel:"a"`
Expand Down
14 changes: 11 additions & 3 deletions exec/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,19 @@ func unmarshalSlice(result Result, val reflect.Value, settings ...ContextApply)
}

for _, i := range nodeset {
var err error
var sliceValue reflect.Value

if sliceElementKind == reflect.Slice {
return fmt.Errorf("slice unmarshals can only operate on 1-dimensional slices")
} else if sliceElementKind == reflect.Struct {
ptr := reflect.New(sliceElement)
ptr.Elem().Set(reflect.Zero(sliceElement))
err = unmarshal(NodeSet{i}, ptr.Interface(), settings...)

err := unmarshal(NodeSet{i}, ptr.Interface(), settings...)
if err != nil {
return err
}

sliceValue = ptr.Elem()
} else {
val, ok := createValue(sliceElementKind, NodeSet{i})
Expand All @@ -143,7 +147,7 @@ func unmarshalSlice(result Result, val reflect.Value, settings ...ContextApply)
sliceValue = val
}

setField("<slice>", val, sliceValue, true)
err := setField("<slice>", val, sliceValue, true)

if err != nil {
return err
Expand Down Expand Up @@ -186,6 +190,10 @@ func setField(name string, field reflect.Value, val reflect.Value, checkSlice bo
return fmt.Errorf("could not set field, %s", name)
}

if !field.CanSet() {
return fmt.Errorf("field %s is not settable", name)
}

if isSlice {
field.Set(reflect.Append(field, ptrVal))
} else {
Expand Down

0 comments on commit 65728c1

Please sign in to comment.