Skip to content

Commit 8b2ce42

Browse files
authored
[ML] Fix a call stack size exception triggered by a negative tickInterval. (#24742)
In certain cases tickInterval mistakenly could end up being negative which made getTickValues() run into a call stack size exception. This PR fixes it by a) adding a check to getTickValues() that interval must not be 0 or smaller and b) changing the way the tickInterval is determined in the Anomaly Explorer Charts.
1 parent 0b74169 commit 8b2ce42

File tree

4 files changed

+23
-10
lines changed

4 files changed

+23
-10
lines changed

x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_distribution.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,10 @@ export class ExplorerChartDistribution extends React.Component {
239239
timeBuckets.setInterval('auto');
240240
const xAxisTickFormat = timeBuckets.getScaledDateFormat();
241241

242-
const emphasisStart = Math.max(config.selectedEarliest, config.plotEarliest);
243-
const emphasisEnd = Math.min(config.selectedLatest, config.plotLatest);
242+
const tickValuesStart = Math.max(config.selectedEarliest, config.plotEarliest);
244243
// +1 ms to account for the ms that was substracted for query aggregations.
245-
const interval = emphasisEnd - emphasisStart + 1;
246-
const tickValues = getTickValues(emphasisStart, interval, config.plotEarliest, config.plotLatest);
244+
const interval = config.selectedLatest - config.selectedEarliest + 1;
245+
const tickValues = getTickValues(tickValuesStart, interval, config.plotEarliest, config.plotLatest);
247246

248247
const xAxis = d3.svg.axis().scale(lineChartXScale)
249248
.orient('bottom')
@@ -283,7 +282,7 @@ export class ExplorerChartDistribution extends React.Component {
283282
.call(yAxis);
284283

285284
if (tooManyBuckets === false) {
286-
removeLabelOverlap(gAxis, emphasisStart, interval, vizWidth);
285+
removeLabelOverlap(gAxis, tickValuesStart, interval, vizWidth);
287286
}
288287
}
289288

x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,10 @@ export class ExplorerChartSingleMetric extends React.Component {
192192
timeBuckets.setInterval('auto');
193193
const xAxisTickFormat = timeBuckets.getScaledDateFormat();
194194

195-
const emphasisStart = Math.max(config.selectedEarliest, config.plotEarliest);
196-
const emphasisEnd = Math.min(config.selectedLatest, config.plotLatest);
195+
const tickValuesStart = Math.max(config.selectedEarliest, config.plotEarliest);
197196
// +1 ms to account for the ms that was substracted for query aggregations.
198-
const interval = emphasisEnd - emphasisStart + 1;
199-
const tickValues = getTickValues(emphasisStart, interval, config.plotEarliest, config.plotLatest);
197+
const interval = config.selectedLatest - config.selectedEarliest + 1;
198+
const tickValues = getTickValues(tickValuesStart, interval, config.plotEarliest, config.plotLatest);
200199

201200
const xAxis = d3.svg.axis().scale(lineChartXScale)
202201
.orient('bottom')
@@ -236,7 +235,7 @@ export class ExplorerChartSingleMetric extends React.Component {
236235
.call(yAxis);
237236

238237
if (tooManyBuckets === false) {
239-
removeLabelOverlap(gAxis, emphasisStart, interval, vizWidth);
238+
removeLabelOverlap(gAxis, tickValuesStart, interval, vizWidth);
240239
}
241240
}
242241

x-pack/plugins/ml/public/util/chart_utils.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ const TICK_DIRECTION = {
239239
// the bounds of earliest and latest. This is useful for the Anomaly Explorer Charts
240240
// to align axis ticks with the gray area resembling the swimlane cell selection.
241241
export function getTickValues(startTimeMs, tickInterval, earliest, latest) {
242+
// A tickInterval equal or smaller than 0 would trigger a call stack exception,
243+
// so we're trying to catch that before it happens.
244+
if (tickInterval <= 0) {
245+
throw Error('tickInterval must be larger than 0.');
246+
}
247+
242248
const tickValues = [startTimeMs];
243249

244250
function addTicks(ts, operator) {

x-pack/plugins/ml/public/util/chart_utils.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ describe('getTickValues', () => {
136136
1519257600000
137137
]);
138138
});
139+
140+
test('invalid tickIntervals trigger an error', () => {
141+
expect(() => {
142+
getTickValues(1518652800000, 0, 1518274800000, 1519635600000);
143+
}).toThrow();
144+
expect(() => {
145+
getTickValues(1518652800000, -604800000, 1518274800000, 1519635600000);
146+
}).toThrow();
147+
});
139148
});
140149

141150
describe('isLabelLengthAboveThreshold', () => {

0 commit comments

Comments
 (0)