diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index de7ff112396a..5455b167684d 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -80,6 +80,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Fix goroutine leak and Elasticsearch output file descriptor leak when output reloading is in use. {issue}10491[10491] {pull}17381[17381] - Fix `setup.dashboards.index` setting not working. {pull}17749[17749] - Fix Elasticsearch license endpoint URL referenced in error message. {issue}17880[17880] {pull}18030[18030] +- Fix panic when assigning a key to a `nil` value in an event. {pull}18143[18143] *Auditbeat* diff --git a/libbeat/common/mapstr.go b/libbeat/common/mapstr.go index 8cf589b0f04a..d70f05dd3493 100644 --- a/libbeat/common/mapstr.go +++ b/libbeat/common/mapstr.go @@ -96,20 +96,26 @@ func (m MapStr) deepUpdateMap(d MapStr, overwrite bool) { } func deepUpdateValue(old interface{}, val MapStr, overwrite bool) interface{} { - if old == nil { - return val - } - switch sub := old.(type) { case MapStr: + if sub == nil { + return val + } + sub.deepUpdateMap(val, overwrite) return sub case map[string]interface{}: + if sub == nil { + return val + } + tmp := MapStr(sub) tmp.deepUpdateMap(val, overwrite) return tmp default: - // This should never happen + // We reach the default branch if old is no map or if old == nil. + // In either case we return `val`, such that the old value is completely + // replaced when merging. return val } } diff --git a/libbeat/common/mapstr_test.go b/libbeat/common/mapstr_test.go index de633ff162ea..e1ffb8f5ee42 100644 --- a/libbeat/common/mapstr_test.go +++ b/libbeat/common/mapstr_test.go @@ -87,6 +87,11 @@ func TestMapStrDeepUpdate(t *testing.T) { MapStr{"a.b": 1}, MapStr{"a": 1, "a.b": 1}, }, + { + MapStr{"a": (MapStr)(nil)}, + MapStr{"a": MapStr{"b": 1}}, + MapStr{"a": MapStr{"b": 1}}, + }, } for i, test := range tests {