[release-11.6.3] FlameGraph: Fix bug for function names that conflict with JavaScript object prototype properties (#106624)
FlameGraph: Fix bug for function names that conflict with JavaScript object prototype properties (#106338)
* grafana-flamegraph: Fix bug for function names that conflict with JavaScript object prototype properties
The bug occurs in the flamegraph data transformation logic where function names from profiling data are used as object
keys without proper prototype pollution protection.
Fixes #106232 #101551
* Fix top table calculations
---------
(cherry picked from commit 6156e9c2d8)
Co-authored-by: Christian Simon <simon@swine.de>
Co-authored-by: vinayteki95 <vinayteki95@users.noreply.github.com>
Co-authored-by: Piotr Jamróz <pm.jamroz@gmail.com>
This commit is contained in:
co-authored by
Christian Simon
vinayteki95
Piotr Jamróz
parent
d6697ddde4
commit
d48d89e993
@@ -75,6 +75,30 @@ describe('nestedSetToLevels', () => {
|
||||
expect(levels[0]).toEqual([n1]);
|
||||
expect(levels[1]).toEqual([n2, n3, n4]);
|
||||
});
|
||||
|
||||
it('handles strings that collide with inherited prototype method names', () => {
|
||||
const frame = createDataFrame({
|
||||
fields: [
|
||||
{ name: 'level', values: [0, 1, 1, 1] },
|
||||
{ name: 'value', values: [10, 5, 3, 1] },
|
||||
{ name: 'label', values: ['toString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf'], type: FieldType.string },
|
||||
{ name: 'self', values: [10, 5, 3, 1] },
|
||||
],
|
||||
});
|
||||
const [levels] = nestedSetToLevels(new FlameGraphDataContainer(frame, { collapsing: true }));
|
||||
|
||||
const n4: LevelItem = { itemIndexes: [3], start: 8, children: [], value: 1, level: 1 };
|
||||
const n3: LevelItem = { itemIndexes: [2], start: 5, children: [], value: 3, level: 1 };
|
||||
const n2: LevelItem = { itemIndexes: [1], start: 0, children: [], value: 5, level: 1 };
|
||||
const n1: LevelItem = { itemIndexes: [0], start: 0, children: [n2, n3, n4], value: 10, level: 0 };
|
||||
|
||||
n2.parents = [n1];
|
||||
n3.parents = [n1];
|
||||
n4.parents = [n1];
|
||||
|
||||
expect(levels[0]).toEqual([n1]);
|
||||
expect(levels[1]).toEqual([n2, n3, n4]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('FlameGraphDataContainer', () => {
|
||||
|
||||
@@ -46,7 +46,7 @@ export function nestedSetToLevels(
|
||||
let offset = 0;
|
||||
|
||||
let parent: LevelItem | undefined = undefined;
|
||||
const uniqueLabels: Record<string, LevelItem[]> = {};
|
||||
const uniqueLabels: Record<string, LevelItem[]> = Object.create(null);
|
||||
|
||||
for (let i = 0; i < container.data.length; i++) {
|
||||
const currentLevel = container.getLevel(i);
|
||||
|
||||
@@ -56,7 +56,7 @@ const FlameGraphTopTableContainer = memo(
|
||||
const table = useMemo(() => {
|
||||
// Group the data by label, we show only one row per label and sum the values
|
||||
// TODO: should be by filename + funcName + linenumber?
|
||||
let filteredTable: { [key: string]: TableData } = {};
|
||||
let filteredTable: { [key: string]: TableData } = Object.create(null);
|
||||
for (let i = 0; i < data.data.length; i++) {
|
||||
const value = data.getValue(i);
|
||||
const valueRight = data.getValueRight(i);
|
||||
|
||||
Reference in New Issue
Block a user