Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: In no-invalid-regexp validate flags also for non-literal patter…
…ns (#16583)

Fixes #16573
  • Loading branch information
trosos committed Nov 27, 2022
1 parent fbcf3ab commit a91332b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 18 deletions.
58 changes: 40 additions & 18 deletions lib/rules/no-invalid-regexp.js
Expand Up @@ -59,6 +59,20 @@ module.exports = {
}
}

/**
* Reports error with the provided message.
* @param {ASTNode} node The node holding the invalid RegExp
* @param {string} message The message to report.
* @returns {void}
*/
function report(node, message) {
context.report({
node,
messageId: "regexMessage",
data: { message }
});
}

/**
* Check if node is a string
* @param {ASTNode} node node to evaluate
Expand Down Expand Up @@ -108,10 +122,13 @@ module.exports = {

/**
* Check syntax error in a given flags.
* @param {string} flags The RegExp flags to validate.
* @param {string|null} flags The RegExp flags to validate.
* @returns {string|null} The syntax error.
*/
function validateRegExpFlags(flags) {
if (!flags) {
return null;
}
try {
validator.validateFlags(flags);
return null;
Expand All @@ -122,34 +139,39 @@ module.exports = {

return {
"CallExpression, NewExpression"(node) {
if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp" || !isString(node.arguments[0])) {
if (node.callee.type !== "Identifier" || node.callee.name !== "RegExp") {
return;
}
const pattern = node.arguments[0].value;

let flags = getFlags(node);

if (flags && allowedFlags) {
flags = flags.replace(allowedFlags, "");
}

const message =
(
flags && validateRegExpFlags(flags)
) ||
(
let message = validateRegExpFlags(flags);

if (message) {
report(node, message);
return;
}

if (!isString(node.arguments[0])) {
return;
}

const pattern = node.arguments[0].value;

message = (

// If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
flags === null
? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
: validateRegExpPattern(pattern, flags.includes("u"))
);
// If flags are unknown, report the regex only if its pattern is invalid both with and without the "u" flag
flags === null
? validateRegExpPattern(pattern, true) && validateRegExpPattern(pattern, false)
: validateRegExpPattern(pattern, flags.includes("u"))
);

if (message) {
context.report({
node,
messageId: "regexMessage",
data: { message }
});
report(node, message);
}
}
};
Expand Down
42 changes: 42 additions & 0 deletions tests/lib/rules/no-invalid-regexp.js
Expand Up @@ -57,6 +57,12 @@ ruleTester.run("no-invalid-regexp", rule, {
options: [{ allowConstructorFlags: ["a"] }]
},

// unknown pattern
"new RegExp(pattern, 'g')",
"new RegExp('.' + '', 'g')",
"new RegExp(pattern, '')",
"new RegExp(pattern)",

// ES2020
"new RegExp('(?<\\\\ud835\\\\udc9c>.)', 'g')",
"new RegExp('(?<\\\\u{1d49c}>.)', 'g')",
Expand Down Expand Up @@ -87,6 +93,14 @@ ruleTester.run("no-invalid-regexp", rule, {
code: "new RegExp('.', 'ga')",
options: [{ allowConstructorFlags: ["a"] }]
},
{
code: "new RegExp(pattern, 'ga')",
options: [{ allowConstructorFlags: ["a"] }]
},
{
code: "new RegExp('.' + '', 'ga')",
options: [{ allowConstructorFlags: ["a"] }]
},
{
code: "new RegExp('.', 'a')",
options: [{ allowConstructorFlags: ["a", "z"] }]
Expand Down Expand Up @@ -237,6 +251,34 @@ ruleTester.run("no-invalid-regexp", rule, {
data: { message: "Invalid regular expression: /\\/: \\ at end of pattern" },
type: "NewExpression"
}]
},

// https://github.com/eslint/eslint/issues/16573
{
code: "RegExp(')' + '', 'a');",
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'a'" },
type: "CallExpression"
}]
},
{
code: "new RegExp('.' + '', 'az');",
options: [{ allowConstructorFlags: ["z"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'a'" },
type: "NewExpression"
}]
},
{
code: "new RegExp(pattern, 'az');",
options: [{ allowConstructorFlags: ["a"] }],
errors: [{
messageId: "regexMessage",
data: { message: "Invalid flags supplied to RegExp constructor 'z'" },
type: "NewExpression"
}]
}
]
});

0 comments on commit a91332b

Please sign in to comment.