Skip to content
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

Closed

Conversation

mscdex
Copy link
Contributor

@mscdex mscdex commented Mar 13, 2017

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), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)
  • tools
  • test

@mscdex mscdex added test Issues and PRs related to the tests. tools Issues and PRs related to the tools directory. labels Mar 13, 2017
@mscdex
Copy link
Contributor Author

mscdex commented Mar 13, 2017

/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;
Copy link
Contributor

@not-an-aardvark not-an-aardvark Mar 14, 2017

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.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know.

Copy link
Contributor Author

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) {
Copy link
Contributor

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./);

Copy link
Contributor Author

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]);
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@mscdex mscdex force-pushed the tools-eslint-regex-dot-escape-rule branch 2 times, most recently from 185f959 to a3a1eda Compare March 14, 2017 09:17
@mscdex
Copy link
Contributor Author

mscdex commented Mar 14, 2017

I've addressed raised concerns and added support for template literals. These new changes resulted in several more instances being found.

CI: https://ci.nodejs.org/job/node-test-pull-request/6832/

@fhinkel
Copy link
Member

fhinkel commented Mar 15, 2017

I think this needs a rebase.

@fhinkel
Copy link
Member

fhinkel commented Mar 26, 2017

ping @mscdex

@mscdex mscdex force-pushed the tools-eslint-regex-dot-escape-rule branch from a3a1eda to 9153949 Compare March 29, 2017 07:29
@mscdex
Copy link
Contributor Author

mscdex commented Mar 29, 2017

@fhinkel Rebased.

@mscdex
Copy link
Contributor Author

mscdex commented Mar 29, 2017

@fhinkel
Copy link
Member

fhinkel commented Mar 29, 2017

Thanks. Landed in 61ebfa8

@fhinkel fhinkel closed this Mar 29, 2017
fhinkel pushed a commit that referenced this pull request Mar 29, 2017
PR-URL: #11834
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Teddy Katz <teddy.katz@gmail.com>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
@mscdex mscdex deleted the tools-eslint-regex-dot-escape-rule branch March 29, 2017 09:21
@jasnell jasnell mentioned this pull request Apr 4, 2017
@gibfahn gibfahn mentioned this pull request Jun 15, 2017
3 tasks
@gibfahn
Copy link
Member

gibfahn commented Jun 17, 2017

Are you willing to backport this to v6.x-staging? If yes please follow the guide and raise a backport PR, if no let me know or add the dont-land-on label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
test Issues and PRs related to the tests. tools Issues and PRs related to the tools directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants