-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tools: add unescaped regexp dot rule to linter #11834
Conversation
/cc @nodejs/testing |
const utilsPath = path.join(__dirname, '..', 'eslint', 'lib', 'ast-utils.js'); | ||
const astUtils = require(utilsPath); | ||
const getLocationFromRangeIndex = astUtils.getLocationFromRangeIndex; | ||
const getRangeIndexFromLocation = astUtils.getRangeIndexFromLocation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods aren't part of the public API, and were removed in ESLint v3.17.0. (Using them for now is probably fine, but they'll need to be changed to sourceCode.getLocFromIndex
and sourceCode.getIndexFromLoc
when ESLint is upgraded.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I've added a check to support the later versions too.
break; | ||
case '.': | ||
if (!escaping) { | ||
if (!inCharClass && (i + 1) < str.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we want to report the node when i + 1 === str.length
? This would cover the case where the .
is at the end of the regex, e.g.
assert.throws(func, /this error message ends with a dot./);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
return { | ||
Literal: function(node) { | ||
if (inRegExp && typeof node.value === 'string' && node.value.length) | ||
regexpBuffer.push([node, node.value]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could cause some weird behavior if the argument to RegExp
isn't just string concatenation:
// 'foo.bar' gets interpreted as a regex pattern
new RegExp(function() {
return crypto.createHash('sha1').update('foo.bar').digest('hex');
}());
Or it could handle character classes incorrectly:
const closingBracket = ']';
new RegExp('[abc' + closingBracket + '.');
There's no perfect solution to this, so it's probably fine as-is if we're not running into cases like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the first example, I originally had it coded differently and actually checked parent nodes when encountering string literals, but that seemed more complicated.
Regarding the second example, I pointed that out in the PR description. I doubt that would ever become a problem in practice though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've re-added the strict parent node checking.
185f959
to
a3a1eda
Compare
I've addressed raised concerns and added support for template literals. These new changes resulted in several more instances being found. |
I think this needs a rebase. |
ping @mscdex |
a3a1eda
to
9153949
Compare
@fhinkel Rebased. |
Thanks. Landed in 61ebfa8 |
PR-URL: #11834 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Teddy Katz <[email protected]> Reviewed-By: Franziska Hinkelmann <[email protected]>
Are you willing to backport this to |
This adds a custom rule to the linter that checks for unescaped "literal" dots in regular expressions. For regexp literals this is straightforward, but it's trickier for
RegExp()
usage because of possible variable text passed to the constructor. This rule tries its best in the constructor scenario by concatenating any/all of the string literals passed to it and checking that.CI: https://ci.nodejs.org/job/node-test-pull-request/6825/
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)