Skip to content

Commit

Permalink
Add keyPrefix to avoid issues with __proto__. [closes #226]
Browse files Browse the repository at this point in the history
Former-commit-id: 55dee782acdd5e28229b1fcb7587424d3fdfd445
  • Loading branch information
jdalton committed Apr 2, 2013
1 parent 4b0d33b commit fd3b62e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
23 changes: 12 additions & 11 deletions lodash.js
Expand Up @@ -29,6 +29,9 @@
/** Used internally to indicate various things */
var indicatorObject = {};

/** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
var keyPrefix = +new Date + '';

/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
Expand Down Expand Up @@ -586,16 +589,14 @@
index = fromIndex - 1;

while (++index < length) {
// manually coerce `value` to a string because `hasOwnProperty`, in some
// older versions of Firefox, coerces objects incorrectly
var key = String(array[index]);
(hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
var key = keyPrefix + array[index];
(cache[key] || (cache[key] = [])).push(array[index]);
}
}
return function(value) {
if (isLarge) {
var key = String(value);
return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
var key = keyPrefix + value;
return cache[key] && indexOf(cache[key], value) > -1;
}
return indexOf(array, value, fromIndex) > -1;
}
Expand Down Expand Up @@ -3623,8 +3624,8 @@
while (++index < length) {
var value = array[index];
if (isLarge) {
var key = String(value);
var inited = hasOwnProperty.call(cache[0], key)
var key = keyPrefix + value;
var inited = cache[0][key]
? !(seen = cache[0][key])
: (seen = cache[0][key] = []);
}
Expand Down Expand Up @@ -4031,8 +4032,8 @@
computed = callback ? callback(value, index, array) : value;

if (isLarge) {
var key = String(computed);
var inited = hasOwnProperty.call(cache, key)
var key = keyPrefix + computed;
var inited = cache[key]
? !(seen = cache[key])
: (seen = cache[key] = []);
}
Expand Down Expand Up @@ -4517,7 +4518,7 @@
function memoize(func, resolver) {
var cache = {};
return function() {
var key = String(resolver ? resolver.apply(this, arguments) : arguments[0]);
var key = keyPrefix + (resolver ? resolver.apply(this, arguments) : arguments[0]);
return hasOwnProperty.call(cache, key)
? cache[key]
: (cache[key] = func.apply(this, arguments));
Expand Down
30 changes: 30 additions & 0 deletions test/test.js
Expand Up @@ -1074,6 +1074,36 @@

/*--------------------------------------------------------------------------*/

QUnit.module('`__proto__` property bugs');

(function() {
var stringLiteral = '__proto__',
stringObject = Object(stringLiteral),
expected = [stringLiteral, stringObject];

var array = _.times(100, function(count) {
return count % 2 ? stringObject : stringLiteral;
});

test('internal data objects should work with the `__proto__` key', function() {
deepEqual(_.difference(array, array), []);
deepEqual(_.intersection(array, array), expected);
deepEqual(_.uniq(array), expected);
deepEqual(_.without.apply(_, [array].concat(array)), []);
});

test('lodash.memoize should memoize values resolved to the `__proto__` key', function() {
var count = 0,
memoized = _.memoize(function() { return ++count; });

memoized('__proto__');
memoized('__proto__');
strictEqual(count, 1);
});
}());

/*--------------------------------------------------------------------------*/

QUnit.module('lodash.groupBy');

(function() {
Expand Down

0 comments on commit fd3b62e

Please sign in to comment.