diff --git a/src/constant.js b/src/constant.js index 22d6e8adc..ae555891e 100644 --- a/src/constant.js +++ b/src/constant.js @@ -27,4 +27,4 @@ export const INVALID_DATE_STRING = 'Invalid Date' // regex export const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/ -export const REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g +export const REGEX_FORMAT = /(?![^\[\]])\[([^\[\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g diff --git a/src/plugin/localizedFormat/utils.js b/src/plugin/localizedFormat/utils.js index b6284d8e9..d002a954b 100644 --- a/src/plugin/localizedFormat/utils.js +++ b/src/plugin/localizedFormat/utils.js @@ -1,6 +1,6 @@ // eslint-disable-next-line import/prefer-default-export export const t = format => - format.replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (_, a, b) => a || b.slice(1)) + format.replace(/(\[(?!\[)[^\]]+])|(MMMM|MM|DD|dddd)/g, (_, a, b) => a || b.slice(1)) export const englishFormats = { LTS: 'h:mm:ss A', @@ -11,7 +11,7 @@ export const englishFormats = { LLLL: 'dddd, MMMM D, YYYY h:mm A' } -export const u = (formatStr, formats) => formatStr.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, a, b) => { +export const u = (formatStr, formats) => formatStr.replace(/(\[(?!\[)[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, a, b) => { const B = b && b.toUpperCase() return a || formats[b] || englishFormats[b] || t(formats[B]) }) diff --git a/test/plugin/localizedFormat.test.js b/test/plugin/localizedFormat.test.js index da5b219e0..3fe16ce36 100644 --- a/test/plugin/localizedFormat.test.js +++ b/test/plugin/localizedFormat.test.js @@ -116,3 +116,12 @@ it('Uses the localized uppercase formats as a base for lowercase formats, if not expect(spanishDate.format(option)).toBe(spanishDate.format(adaptedFormat)) }) }) + +it('ReDos attack', () => { + const longFmt = '['.repeat(100000) + '\u0000' + const start = Date.now() + const output = dayjs().format(longFmt) + const elapsed = Date.now() - start + expect(output).toBe(longFmt) + expect(elapsed).toBeLessThan(3000) +})