Skip to content

Commit

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

Closes #19206

(cherry picked from commit 0940e25)

Co-authored-by: ian woolf <btw515wolf2@gmail.com>
  • Loading branch information
jsoriano and ianwoolf committed Jun 22, 2021
1 parent b92cb0f commit 51c97b9
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 @@ -169,6 +169,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Drop aws.vpcflow.pkt_srcaddr and aws.vpcflow.pkt_dstaddr when equal to "-". {pull}22721[22721] {issue}22716[22716]
- Fix bug in aws-s3 input where the end of gzipped log files might have been discarded. {pull}26260[26260]
- o365: Avoid mapping exception for `Parameters` and `ExtendedProperties` fields of string type. {pull}26164[26164]
- 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 @@ -121,6 +121,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 51c97b9

Please sign in to comment.