|
12 | 12 | var undefined;
|
13 | 13 |
|
14 | 14 | /** Used as the semantic version number. */
|
15 |
| - var VERSION = '4.17.20'; |
| 15 | + var VERSION = '4.17.21'; |
16 | 16 |
|
17 | 17 | /** Used as the size to enable large array optimizations. */
|
18 | 18 | var LARGE_ARRAY_SIZE = 200;
|
19 | 19 |
|
20 | 20 | /** Error message constants. */
|
21 | 21 | var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
|
22 |
| - FUNC_ERROR_TEXT = 'Expected a function'; |
| 22 | + FUNC_ERROR_TEXT = 'Expected a function', |
| 23 | + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; |
23 | 24 |
|
24 | 25 | /** Used to stand-in for `undefined` hash values. */
|
25 | 26 | var HASH_UNDEFINED = '__lodash_hash_undefined__';
|
|
152 | 153 | var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
|
153 | 154 | reHasRegExpChar = RegExp(reRegExpChar.source);
|
154 | 155 |
|
155 |
| - /** Used to match leading and trailing whitespace. */ |
156 |
| - var reTrim = /^\s+|\s+$/g, |
157 |
| - reTrimStart = /^\s+/, |
158 |
| - reTrimEnd = /\s+$/; |
| 156 | + /** Used to match leading whitespace. */ |
| 157 | + var reTrimStart = /^\s+/; |
| 158 | + |
| 159 | + /** Used to match a single whitespace character. */ |
| 160 | + var reWhitespace = /\s/; |
159 | 161 |
|
160 | 162 | /** Used to match wrap detail comments. */
|
161 | 163 | var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
|
|
165 | 167 | /** Used to match words composed of alphanumeric characters. */
|
166 | 168 | var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
167 | 169 |
|
| 170 | + /** |
| 171 | + * Used to validate the `validate` option in `_.template` variable. |
| 172 | + * |
| 173 | + * Forbids characters which could potentially change the meaning of the function argument definition: |
| 174 | + * - "()," (modification of function parameters) |
| 175 | + * - "=" (default value) |
| 176 | + * - "[]{}" (destructuring of function parameters) |
| 177 | + * - "/" (beginning of a comment) |
| 178 | + * - whitespace |
| 179 | + */ |
| 180 | + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; |
| 181 | + |
168 | 182 | /** Used to match backslashes in property paths. */
|
169 | 183 | var reEscapeChar = /\\(\\)?/g;
|
170 | 184 |
|
|
993 | 1007 | });
|
994 | 1008 | }
|
995 | 1009 |
|
| 1010 | + /** |
| 1011 | + * The base implementation of `_.trim`. |
| 1012 | + * |
| 1013 | + * @private |
| 1014 | + * @param {string} string The string to trim. |
| 1015 | + * @returns {string} Returns the trimmed string. |
| 1016 | + */ |
| 1017 | + function baseTrim(string) { |
| 1018 | + return string |
| 1019 | + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') |
| 1020 | + : string; |
| 1021 | + } |
| 1022 | + |
996 | 1023 | /**
|
997 | 1024 | * The base implementation of `_.unary` without support for storing metadata.
|
998 | 1025 | *
|
|
1326 | 1353 | : asciiToArray(string);
|
1327 | 1354 | }
|
1328 | 1355 |
|
| 1356 | + /** |
| 1357 | + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace |
| 1358 | + * character of `string`. |
| 1359 | + * |
| 1360 | + * @private |
| 1361 | + * @param {string} string The string to inspect. |
| 1362 | + * @returns {number} Returns the index of the last non-whitespace character. |
| 1363 | + */ |
| 1364 | + function trimmedEndIndex(string) { |
| 1365 | + var index = string.length; |
| 1366 | + |
| 1367 | + while (index-- && reWhitespace.test(string.charAt(index))) {} |
| 1368 | + return index; |
| 1369 | + } |
| 1370 | + |
1329 | 1371 | /**
|
1330 | 1372 | * Used by `_.unescape` to convert HTML entities to characters.
|
1331 | 1373 | *
|
|
12494 | 12536 | if (typeof value != 'string') {
|
12495 | 12537 | return value === 0 ? value : +value;
|
12496 | 12538 | }
|
12497 |
| - value = value.replace(reTrim, ''); |
| 12539 | + value = baseTrim(value); |
12498 | 12540 | var isBinary = reIsBinary.test(value);
|
12499 | 12541 | return (isBinary || reIsOctal.test(value))
|
12500 | 12542 | ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
|
|
14866 | 14908 | if (!variable) {
|
14867 | 14909 | source = 'with (obj) {\n' + source + '\n}\n';
|
14868 | 14910 | }
|
| 14911 | + // Throw an error if a forbidden character was found in `variable`, to prevent |
| 14912 | + // potential command injection attacks. |
| 14913 | + else if (reForbiddenIdentifierChars.test(variable)) { |
| 14914 | + throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT); |
| 14915 | + } |
| 14916 | + |
14869 | 14917 | // Cleanup code by stripping empty strings.
|
14870 | 14918 | source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
14871 | 14919 | .replace(reEmptyStringMiddle, '$1')
|
|
14979 | 15027 | function trim(string, chars, guard) {
|
14980 | 15028 | string = toString(string);
|
14981 | 15029 | if (string && (guard || chars === undefined)) {
|
14982 |
| - return string.replace(reTrim, ''); |
| 15030 | + return baseTrim(string); |
14983 | 15031 | }
|
14984 | 15032 | if (!string || !(chars = baseToString(chars))) {
|
14985 | 15033 | return string;
|
|
15014 | 15062 | function trimEnd(string, chars, guard) {
|
15015 | 15063 | string = toString(string);
|
15016 | 15064 | if (string && (guard || chars === undefined)) {
|
15017 |
| - return string.replace(reTrimEnd, ''); |
| 15065 | + return string.slice(0, trimmedEndIndex(string) + 1); |
15018 | 15066 | }
|
15019 | 15067 | if (!string || !(chars = baseToString(chars))) {
|
15020 | 15068 | return string;
|
|
0 commit comments