terser
Advanced tools
Comparing version 5.14.1 to 5.14.2
# Changelog | ||
## v5.14.2 | ||
- Security fix for RegExps that should not be evaluated (regexp DDOS) | ||
- Source maps improvements (#1211) | ||
- Performance improvements in long property access evaluation (#1213) | ||
## v5.14.1 | ||
@@ -209,2 +215,9 @@ - keep_numbers option added to TypeScript defs (#1208) | ||
----- | ||
## v4.8.1 (backport) | ||
- Security fix for RegExps that should not be evaluated (regexp DDOS) | ||
## v4.8.0 | ||
@@ -211,0 +224,0 @@ |
@@ -49,3 +49,4 @@ /*********************************************************************** | ||
string_template, | ||
regexp_source_fix | ||
regexp_source_fix, | ||
regexp_is_safe, | ||
} from "../utils/index.js"; | ||
@@ -133,3 +134,3 @@ import { | ||
let evaluated = compressor.evaluated_regexps.get(this.value); | ||
if (evaluated === undefined) { | ||
if (evaluated === undefined && regexp_is_safe(this.value.source)) { | ||
try { | ||
@@ -347,3 +348,3 @@ const { source, flags } = this.value; | ||
def_eval(AST_PropAccess, function (compressor, depth) { | ||
const obj = this.expression._eval(compressor, depth); | ||
let obj = this.expression._eval(compressor, depth + 1); | ||
if (obj === nullish || (this.optional && obj == null)) return nullish; | ||
@@ -358,3 +359,2 @@ if (compressor.option("unsafe")) { | ||
var exp = this.expression; | ||
var val; | ||
if (is_undeclared_ref(exp)) { | ||
@@ -376,20 +376,20 @@ | ||
return this; | ||
val = global_objs[exp.name]; | ||
obj = global_objs[exp.name]; | ||
} else { | ||
val = exp._eval(compressor, depth + 1); | ||
if (val instanceof RegExp) { | ||
if (obj instanceof RegExp) { | ||
if (key == "source") { | ||
return regexp_source_fix(val.source); | ||
return regexp_source_fix(obj.source); | ||
} else if (key == "flags" || regexp_flags.has(key)) { | ||
return val[key]; | ||
return obj[key]; | ||
} | ||
} | ||
if (!val || val === exp || !HOP(val, key)) | ||
if (!obj || obj === exp || !HOP(obj, key)) | ||
return this; | ||
if (typeof val == "function") | ||
if (typeof obj == "function") | ||
switch (key) { | ||
case "name": | ||
return val.node.name ? val.node.name.name : ""; | ||
return obj.node.name ? obj.node.name.name : ""; | ||
case "length": | ||
return val.node.length_property(); | ||
return obj.node.length_property(); | ||
default: | ||
@@ -399,3 +399,3 @@ return this; | ||
} | ||
return val[key]; | ||
return obj[key]; | ||
} | ||
@@ -402,0 +402,0 @@ return this; |
@@ -252,3 +252,11 @@ /*********************************************************************** | ||
} | ||
const all_flags = "gimuy"; | ||
// Subset of regexps that is not going to cause regexp based DDOS | ||
// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS | ||
const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/; | ||
/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */ | ||
export const regexp_is_safe = (source) => re_safe_regexp.test(source); | ||
const all_flags = "dgimsuy"; | ||
function sort_regexp_flags(flags) { | ||
@@ -255,0 +263,0 @@ const existing_flags = new Set(flags.split("")); |
@@ -7,3 +7,3 @@ { | ||
"license": "BSD-2-Clause", | ||
"version": "5.14.1", | ||
"version": "5.14.2", | ||
"engines": { | ||
@@ -10,0 +10,0 @@ "node": ">=10" |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
2034535
57996