From 1f43580bc5ea32e3e01f4ea230a7c7b56b8c3be6 Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Sun, 20 Mar 2022 00:27:22 +0100 Subject: [PATCH] Replace stacktrace splitting logic to resolve a REDoS vulnerability --- src/parse-stacktrace.js | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/parse-stacktrace.js b/src/parse-stacktrace.js index b83f059..ccc7132 100644 --- a/src/parse-stacktrace.js +++ b/src/parse-stacktrace.js @@ -8,7 +8,7 @@ const defaultValue = require("default-value"); // I'm so, so sorry... let lineRegex = /\s+at\s+(?:(?:((?:[^\[\n])+)\[as ([^\]]+)\] |((?:[^\(\n])+))\(([^\)\n]+)\)|([^\n]+))(?:\n|$)/gm; let geckoLineRegex = /^([^@\n]*)@(.+)/gm; -let positionRegex = /(.+):(\d+):(\d+)/; +let numberRegex = /^\d+$/; function maybeTrim(value) { if (value != null) { @@ -24,17 +24,35 @@ function maybeTrim(value) { } } +function isLocation(locationString) { + return (locationString.split(":").length > 2); +} + +function splitLocation(locationString) { + let parts = locationString.split(":"); + + if (parts.length > 2) { + let pathPartCount = parts.length - 2; + + return [ + parts.slice(0, pathPartCount).join(":"), + parts[pathPartCount], + parts[pathPartCount + 1], + ]; + } +} + function parseLocation(locationString) { if (locationString === "") { return { anonymous: true }; } else { - let match = positionRegex.exec(locationString); + let parts = splitLocation(locationString); - if (match != null) { + if (parts != null && numberRegex.test(parts[1]) && numberRegex.test(parts[2])) { return { - path: match[1], - line: parseInt(match[2]), - column: parseInt(match[3]) + path: parts[0], + line: parseInt(parts[1]), + column: parseInt(parts[2]) }; } else { throw new Error(`Could not parse location from string: ${locationString}`); @@ -91,7 +109,7 @@ module.exports = function parseStackTrace(error) { let firstStackLine = lines .map((line) => line.trim()) - .findIndex((line) => positionRegex.test(line)); + .findIndex((line) => isLocation(line)); if (firstStackLine !== -1) { let cleanStack = lines