CVE-2024-27088 (published 2024-02-26T17:15Z)

es5-ext contains ECMAScript 5 extensions. Passing functions with very long names or complex default argument names into `function#copy` or `function#toStringTokens` may cause the script to stall. The vulnerability is patched in v0.10.63.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/medikoo/es5-ext
commit_details: repo_url: https://github.com/medikoo/es5-ext
author: Mariusz Nowak
author_date: 2024-02-19 17:38:29+01:00
msg: fix: Do not rely on problematic regex

Addresses #201
repository: repo_url: https://github.com/medikoo/es5-ext
repo_name: medikoo/es5-ext
description: ECMAScript extensions (with respect to upcoming ECMAScript features)
repo_language: JavaScript
owner: medikoo
file_changes: filename: copy.js
change_type: ModificationType.MODIFY
diff: @@ -1,19 +1,20 @@
 "use strict";
 
 var mixin         = require("../../object/mixin")
-  , validFunction = require("../valid-function")
-  , re            = /^\s*function\s*([\0-')-\uffff]+)*\s*\(([\0-(*-\uffff]*)\)\s*\{/;
+  , validFunction = require("../valid-function");
 
 module.exports = function () {
-	var match = String(validFunction(this)).match(re), fn;
+	validFunction(this);
 
+	var args = [];
+	for (var i = 0; i < this.length; ++i) args.push("arg" + (i + 1));
 	// eslint-disable-next-line no-new-func
-	fn = new Function(
+	var fn = new Function(
 		"fn",
 		"return function " +
-			match[1].trim() +
+			(this.name || "") +
 			"(" +
-			match[2] +
+			args.join(", ") +
 			") { return fn.apply(this, arguments); };"
 	)(this);
 	try { mixin(fn, this); }

programming_language: JavaScript
repo_url: https://github.com/medikoo/es5-ext
commit_details: repo_url: https://github.com/medikoo/es5-ext
author: Mariusz Nowak
author_date: 2024-02-21 16:33:49+01:00
msg: fix: Support ES2015+ function definitions in `function#toStringTokens()`

Additionally revert from problematic regex based implementation. Addresses #021
repository: repo_url: https://github.com/medikoo/es5-ext
repo_name: medikoo/es5-ext
description: ECMAScript extensions (with respect to upcoming ECMAScript features)
repo_language: JavaScript
owner: medikoo
file_changes: filename: to-string-tokens.js
change_type: ModificationType.MODIFY
diff: @@ -1,17 +1,52 @@
 "use strict";
 
-var validFunction = require("../valid-function");
+var isValue       = require("../../object/is-value")
+  , esniff        = require("esniff")
+  , validFunction = require("../valid-function");
 
-var re1 = /^\s*function[\0-')-\uffff]*\(([\0-(*-\uffff]*)\)\s*\{([\0-\uffff]*)\}\s*$/
-  , re2 = /^\s*\(?([\0-'*-\uffff]*)\)?\s*=>\s*(\{?[\0-\uffff]*\}?)\s*$/;
+var classRe = /^\s*class[\s{/}]/;
 
 module.exports = function () {
-	var str = String(validFunction(this)), data = str.match(re1);
-	if (!data) {
-		data = str.match(re2);
-		if (!data) throw new Error("Unrecognized string format");
-		data[1] = data[1].trim();
-		if (data[2][0] === "{") data[2] = data[2].trim().slice(1, -1);
-	}
-	return { args: data[1], body: data[2] };
+	var str = String(validFunction(this));
+	if (classRe.test(str)) throw new Error("Class methods are not supported");
+
+	var argsStartIndex
+	  , argsEndIndex
+	  , bodyStartIndex
+	  , bodyEndReverseIndex = -1
+	  , shouldTrimArgs = false;
+
+	esniff(str, function (emitter, accessor) {
+		emitter.once("trigger:(", function () { argsStartIndex = accessor.index + 1; });
+		emitter.once("trigger:=", function () {
+			if (isValue(argsStartIndex)) return;
+			argsStartIndex = 0;
+			argsEndIndex = accessor.index;
+			shouldTrimArgs = true;
+			if (!accessor.skipCodePart("=>")) {
+				throw new Error("Unexpected function string: " + str);
+			}
+			accessor.skipWhitespace();
+			if (!accessor.skipCodePart("{")) bodyEndReverseIndex = Infinity;
+			bodyStartIndex = accessor.index;
+		});
+		emitter.on("trigger:)", function () {
+			if (accessor.scopeDepth) return;
+			argsEndIndex = accessor.index;
+			accessor.skipCodePart(")");
+			accessor.skipWhitespace();
+			if (accessor.skipCodePart("=>")) {
+				accessor.skipWhitespace();
+				if (!accessor.skipCodePart("{")) bodyEndReverseIndex = Infinity;
+			} else if (!accessor.skipCodePart("{")) {
+				throw new Error("Unexpected function string: " + str);
+			}
+			bodyStartIndex = accessor.index;
+			accessor.stop();
+		});
+	});
+
+	var argsString = str.slice(argsStartIndex, argsEndIndex);
+	if (shouldTrimArgs) argsString = argsString.trim();
+	return { args: argsString, body: str.slice(bodyStartIndex, bodyEndReverseIndex) };
 };

programming_language: JavaScript
filename: package.json
change_type: ModificationType.MODIFY
diff: @@ -25,6 +25,7 @@
 	"dependencies": {
 		"es6-iterator": "^2.0.3",
 		"es6-symbol": "^3.1.3",
+		"esniff": "^2.0.1",
 		"next-tick": "^1.1.0"
 	},
 	"devDependencies": {

programming_language: Go
filename: to-string-tokens.js
change_type: ModificationType.MODIFY
diff: @@ -10,10 +10,10 @@ module.exports = function (t, a) {
 	a.deep(t.call(function () {}), { args: "", body: "" });
 	// eslint-disable-next-line no-unused-vars
 	a.deep(t.call(function (raz) {}), { args: "raz", body: "" });
-	a.deep(t.call(function () { Object(); }), { args: "", body: " Object(); " });
+	a.deep(t.call(function () { return {}; }), { args: "", body: " return {}; " });
 
 	try {
-		eval("(() => {})");
+		eval("((foo = bar) => {})");
 	} catch (e) {
 		// Non ES2015 env
 		return;
@@ -23,4 +23,9 @@ module.exports = function (t, a) {
 	a.deep(t.call(eval("((elo) => foo)")), { args: "elo", body: "foo" });
 	a.deep(t.call(eval("(elo => foo)")), { args: "elo", body: "foo" });
 	a.deep(t.call(eval("((elo, bar) => foo())")), { args: "elo, bar", body: "foo()" });
+	a.deep(t.call(eval("foo=>bar")), { args: "foo", body: "bar" });
+	a.deep(t.call(eval("(foo = { marko: (elo) => { someFunct(); } }) => { body(); }")), {
+		args: "foo = { marko: (elo) => { someFunct(); } }",
+		body: " body(); "
+	});
 };

programming_language: JavaScript