diff --git a/CHANGELOG.md b/CHANGELOG.md index 08da799fc4..1b2aacf7e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ + +## [2.13.4](https://github.com/jshint/jshint/compare/2.13.3...v2.13.4) (2022-01-24) + +### Bug Fixes + +* Remove shelljs ([eb4609a](https://github.com/jshint/jshint/commit/eb4609a)) + ## [2.13.3](https://github.com/jshint/jshint/compare/2.13.2...v2.13.3) (2022-01-05) diff --git a/dist/jshint-rhino.js b/dist/jshint-rhino.js index 068e40bcc0..7ff7ff6544 100755 --- a/dist/jshint-rhino.js +++ b/dist/jshint-rhino.js @@ -1,6 +1,6 @@ #!/usr/bin/env rhino var window = {}; -/*! 2.13.3 */ +/*! 2.13.4 */ var JSHINT; if (typeof window === 'undefined') window = {}; (function () { @@ -1442,14 +1442,15 @@ function isUndefined(arg) { var undefined; /** Used as the semantic version number. */ - var VERSION = '4.17.20'; + var VERSION = '4.17.21'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Error message constants. */ var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', - FUNC_ERROR_TEXT = 'Expected a function'; + FUNC_ERROR_TEXT = 'Expected a function', + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = '__lodash_hash_undefined__'; @@ -1582,10 +1583,11 @@ function isUndefined(arg) { var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); - /** Used to match leading and trailing whitespace. */ - var reTrim = /^\s+|\s+$/g, - reTrimStart = /^\s+/, - reTrimEnd = /\s+$/; + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; /** Used to match wrap detail comments. */ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, @@ -1595,6 +1597,18 @@ function isUndefined(arg) { /** Used to match words composed of alphanumeric characters. */ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + /** + * Used to validate the `validate` option in `_.template` variable. + * + * Forbids characters which could potentially change the meaning of the function argument definition: + * - "()," (modification of function parameters) + * - "=" (default value) + * - "[]{}" (destructuring of function parameters) + * - "/" (beginning of a comment) + * - whitespace + */ + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; + /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; @@ -2423,6 +2437,19 @@ function isUndefined(arg) { }); } + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + /** * The base implementation of `_.unary` without support for storing metadata. * @@ -2756,6 +2783,21 @@ function isUndefined(arg) { : asciiToArray(string); } + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + /** * Used by `_.unescape` to convert HTML entities to characters. * @@ -13924,7 +13966,7 @@ function isUndefined(arg) { if (typeof value != 'string') { return value === 0 ? value : +value; } - value = value.replace(reTrim, ''); + value = baseTrim(value); var isBinary = reIsBinary.test(value); return (isBinary || reIsOctal.test(value)) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) @@ -16296,6 +16338,12 @@ function isUndefined(arg) { if (!variable) { source = 'with (obj) {\n' + source + '\n}\n'; } + // Throw an error if a forbidden character was found in `variable`, to prevent + // potential command injection attacks. + else if (reForbiddenIdentifierChars.test(variable)) { + throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT); + } + // Cleanup code by stripping empty strings. source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) .replace(reEmptyStringMiddle, '$1') @@ -16409,7 +16457,7 @@ function isUndefined(arg) { function trim(string, chars, guard) { string = toString(string); if (string && (guard || chars === undefined)) { - return string.replace(reTrim, ''); + return baseTrim(string); } if (!string || !(chars = baseToString(chars))) { return string; @@ -16444,7 +16492,7 @@ function isUndefined(arg) { function trimEnd(string, chars, guard) { string = toString(string); if (string && (guard || chars === undefined)) { - return string.replace(reTrimEnd, ''); + return string.slice(0, trimmedEndIndex(string) + 1); } if (!string || !(chars = baseToString(chars))) { return string; diff --git a/dist/jshint.js b/dist/jshint.js index d0cf46993f..13bc2fe3e5 100644 --- a/dist/jshint.js +++ b/dist/jshint.js @@ -1,4 +1,4 @@ -/*! 2.13.3 */ +/*! 2.13.4 */ var JSHINT; if (typeof window === 'undefined') window = {}; (function () { @@ -1440,14 +1440,15 @@ function isUndefined(arg) { var undefined; /** Used as the semantic version number. */ - var VERSION = '4.17.20'; + var VERSION = '4.17.21'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Error message constants. */ var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', - FUNC_ERROR_TEXT = 'Expected a function'; + FUNC_ERROR_TEXT = 'Expected a function', + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = '__lodash_hash_undefined__'; @@ -1580,10 +1581,11 @@ function isUndefined(arg) { var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); - /** Used to match leading and trailing whitespace. */ - var reTrim = /^\s+|\s+$/g, - reTrimStart = /^\s+/, - reTrimEnd = /\s+$/; + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; /** Used to match wrap detail comments. */ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, @@ -1593,6 +1595,18 @@ function isUndefined(arg) { /** Used to match words composed of alphanumeric characters. */ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + /** + * Used to validate the `validate` option in `_.template` variable. + * + * Forbids characters which could potentially change the meaning of the function argument definition: + * - "()," (modification of function parameters) + * - "=" (default value) + * - "[]{}" (destructuring of function parameters) + * - "/" (beginning of a comment) + * - whitespace + */ + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; + /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; @@ -2421,6 +2435,19 @@ function isUndefined(arg) { }); } + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + /** * The base implementation of `_.unary` without support for storing metadata. * @@ -2754,6 +2781,21 @@ function isUndefined(arg) { : asciiToArray(string); } + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + /** * Used by `_.unescape` to convert HTML entities to characters. * @@ -13922,7 +13964,7 @@ function isUndefined(arg) { if (typeof value != 'string') { return value === 0 ? value : +value; } - value = value.replace(reTrim, ''); + value = baseTrim(value); var isBinary = reIsBinary.test(value); return (isBinary || reIsOctal.test(value)) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) @@ -16294,6 +16336,12 @@ function isUndefined(arg) { if (!variable) { source = 'with (obj) {\n' + source + '\n}\n'; } + // Throw an error if a forbidden character was found in `variable`, to prevent + // potential command injection attacks. + else if (reForbiddenIdentifierChars.test(variable)) { + throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT); + } + // Cleanup code by stripping empty strings. source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) .replace(reEmptyStringMiddle, '$1') @@ -16407,7 +16455,7 @@ function isUndefined(arg) { function trim(string, chars, guard) { string = toString(string); if (string && (guard || chars === undefined)) { - return string.replace(reTrim, ''); + return baseTrim(string); } if (!string || !(chars = baseToString(chars))) { return string; @@ -16442,7 +16490,7 @@ function isUndefined(arg) { function trimEnd(string, chars, guard) { string = toString(string); if (string && (guard || chars === undefined)) { - return string.replace(reTrimEnd, ''); + return string.slice(0, trimmedEndIndex(string) + 1); } if (!string || !(chars = baseToString(chars))) { return string; diff --git a/package-lock.json b/package-lock.json index dc2ddde935..59796046e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jshint", - "version": "2.13.3", + "version": "2.13.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jshint", - "version": "2.13.3", + "version": "2.13.4", "license": "MIT", "dependencies": { "cli": "~1.0.0", diff --git a/package.json b/package.json index cd7033c0d3..bde37c08db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jshint", - "version": "2.13.3", + "version": "2.13.4", "homepage": "http://jshint.com/", "description": "Static analysis tool for JavaScript", "author": {