From 47097de8338260c11cd03fda72ff013c77ec27f5 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 18 Jun 2019 13:12:27 -0400 Subject: [PATCH] Fix bug / leak in JS function processors (#12600) (#12604) In an effort to minimize allocations a slice used to hold function arguments is reused rather than allocation new each time a Javascript function processor is used. However there was a typo in re-slicing code so instead of reseting the length to 0 it was a no-op. Hence all future invocations appended to the slice causing a leak. This affects code that uses native Javascript functions in a processor chain (e.g. `new process.Chain().Add(function(event) { event.Put("x", "y"); }).Build()`). (cherry picked from commit f69330a7b5224d5ec5698f48aab85a199f6bee17) --- CHANGELOG.asciidoc | 1 + .../script/javascript/module/processor/chain.go | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 15338b7b06f8..5b90a7a7c283 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -66,6 +66,7 @@ https://github.com/elastic/beats/compare/v7.1.1...v7.2.0[View commits] - Add host.os.codename to fields.yml. {pull}12261[12261] - Fix `@timestamp` being duplicated in events if `@timestamp` is set in a processor (or by any code utilizing `PutValue()` on a `beat.Event`). +- Fix leak in script processor when using Javascript functions in a processor chain. {pull}12600[12600] *Auditbeat* diff --git a/libbeat/processors/script/javascript/module/processor/chain.go b/libbeat/processors/script/javascript/module/processor/chain.go index f86300c213b4..dd61022c29cc 100644 --- a/libbeat/processors/script/javascript/module/processor/chain.go +++ b/libbeat/processors/script/javascript/module/processor/chain.go @@ -83,7 +83,7 @@ func (b *chainBuilder) Add(call goja.FunctionCall) goja.Value { case *beatProcessor: b.procs = append(b.procs, v.p) case func(goja.FunctionCall) goja.Value: - b.procs = append(b.procs, &jsProcessor{fn: v}) + b.procs = append(b.procs, newJSProcessor(v)) default: panic(b.runtime.NewGoError(errors.Errorf("arg0 must be a processor object, but got %T", a0.Export()))) } @@ -119,9 +119,12 @@ type jsProcessor struct { call goja.FunctionCall } +func newJSProcessor(fn jsFunction) *jsProcessor { + return &jsProcessor{fn: fn, call: goja.FunctionCall{Arguments: make([]goja.Value, 1)}} +} + func (p *jsProcessor) run(event javascript.Event) error { - p.call.Arguments = p.call.Arguments[0:] - p.call.Arguments = append(p.call.Arguments, event.JSObject()) + p.call.Arguments[0] = event.JSObject() p.fn(p.call) return nil }