Skip to content

Commit

Permalink
Clone value when copy fields in processors to avoid crash (elastic#20500
Browse files Browse the repository at this point in the history
)

Closes elastic#19206
  • Loading branch information
ianwoolf authored Aug 19, 2020
1 parent 73f8bea commit 0940e25
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Fix `cisco` asa and ftd parsing of messages 106102 and 106103. {pull}20469[20469]
- Improve validation checks for Azure configuration {issue}20369[20369] {pull}20389[20389]
- Fix event.kind for system/syslog pipeline {issue}20365[20365] {pull}20390[20390]
- Clone value when copy fields in processors to avoid crash. {issue}19206[19206] {pull}20500[20500]

*Heartbeat*

Expand Down
23 changes: 22 additions & 1 deletion libbeat/processors/actions/copy_fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (f *copyFields) copyField(from string, to string, fields common.MapStr) err
return fmt.Errorf("could not fetch value for key: %s, Error: %s", from, err)
}

_, err = fields.Put(to, value)
_, err = fields.Put(to, cloneValue(value))
if err != nil {
return fmt.Errorf("could not copy value to %s: %v, %+v", to, value, err)
}
Expand All @@ -114,3 +114,24 @@ func (f *copyFields) copyField(from string, to string, fields common.MapStr) err
func (f *copyFields) String() string {
return "copy_fields=" + fmt.Sprintf("%+v", f.config.Fields)
}

// cloneValue returns a shallow copy of a map. All other types are passed
// through in the return. This should be used when making straight copies of
// maps without doing any type conversions.
func cloneValue(value interface{}) interface{} {
switch v := value.(type) {
case common.MapStr:
return v.Clone()
case map[string]interface{}:
return common.MapStr(v).Clone()
case []interface{}:
len := len(v)
newArr := make([]interface{}, len)
for idx, val := range v {
newArr[idx] = cloneValue(val)
}
return newArr
default:
return value
}
}
23 changes: 23 additions & 0 deletions libbeat/processors/actions/copy_fields_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,29 @@ func TestCopyFields(t *testing.T) {
"message": 42,
},
},
"copy map from nested key message.original to top level field message_copied": {
FromTo: fromTo{
From: "message.original",
To: "message_copied",
},
Input: common.MapStr{
"message": common.MapStr{
"original": common.MapStr{
"original": "original",
},
},
},
Expected: common.MapStr{
"message": common.MapStr{
"original": common.MapStr{
"original": "original",
},
},
"message_copied": common.MapStr{
"original": "original",
},
},
},
}

for name, test := range tests {
Expand Down

0 comments on commit 0940e25

Please sign in to comment.