From b1c73a9984bcd1eb44a34e9e0fcbc025f45f5fa0 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Wed, 22 Mar 2023 15:17:47 +0100 Subject: [PATCH] [v9.4.x] SQL Datasources: Prevent Call Stack Overflows with Large Numbers of Values for Variable (#65182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SQL Datasources: Prevent Call Stack Overflows with Large Numbers of Values for Variable (#64937) * Push values with every map call to avoid hitting the maximum call stack size. * Add test and refactor to for of * Use native fill instead of lodash --------- Co-authored-by: Zoltán Bedi (cherry picked from commit bf687fff45cdc0da716c69a916caa3c86d0f8d78) Co-authored-by: Kyle Cunningham --- .../plugins/sql/ResponseParser.test.ts | 23 +++++++++++++++++++ .../features/plugins/sql/ResponseParser.ts | 12 ++++------ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 public/app/features/plugins/sql/ResponseParser.test.ts diff --git a/public/app/features/plugins/sql/ResponseParser.test.ts b/public/app/features/plugins/sql/ResponseParser.test.ts new file mode 100644 index 00000000000..1913fa298c0 --- /dev/null +++ b/public/app/features/plugins/sql/ResponseParser.test.ts @@ -0,0 +1,23 @@ +import { DataFrameDTO, FieldType, MutableDataFrame } from '@grafana/data'; + +import { ResponseParser } from './ResponseParser'; + +describe('transformMetricFindResponse function', () => { + it('should handle big arrays', () => { + const responseParser = new ResponseParser(); + const stringValues = new Array(150_000).fill('a'); + const numberValues = new Array(150_000).fill(1); + + const frame: DataFrameDTO = { + fields: [ + { name: 'name', type: FieldType.string, values: stringValues }, + { name: 'value', type: FieldType.number, values: numberValues }, + ], + }; + + const dataFrame = new MutableDataFrame(frame); + const result = responseParser.transformMetricFindResponse(dataFrame); + + expect(result).toHaveLength(2); + }); +}); diff --git a/public/app/features/plugins/sql/ResponseParser.ts b/public/app/features/plugins/sql/ResponseParser.ts index 3de28c88edd..fcb12f4e913 100644 --- a/public/app/features/plugins/sql/ResponseParser.ts +++ b/public/app/features/plugins/sql/ResponseParser.ts @@ -14,13 +14,11 @@ export class ResponseParser implements ResponseParserType { values.push({ text: '' + textField.values.get(i), value: '' + valueField.values.get(i) }); } } else { - values.push( - ...frame.fields - .flatMap((f) => f.values.toArray()) - .map((v) => ({ - text: v, - })) - ); + for (const field of frame.fields) { + for (const value of field.values.toArray()) { + values.push({ text: value }); + } + } } return uniqBy(values, 'text');