Skip to content

Commit d6c5b37

Browse files
committed
[Fix] do not allow Symbol.toStringTag to masquerade as builtins
1 parent 7c4e6fd commit d6c5b37

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

index.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,18 @@ function quote(s) {
210210
return String(s).replace(/"/g, '"');
211211
}
212212

213-
function isArray(obj) { return toStr(obj) === '[object Array]'; }
214-
function isDate(obj) { return toStr(obj) === '[object Date]'; }
215-
function isRegExp(obj) { return toStr(obj) === '[object RegExp]'; }
216-
function isError(obj) { return toStr(obj) === '[object Error]'; }
213+
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
214+
215+
function isArray(obj) { return toStr(obj) === '[object Array]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
216+
function isDate(obj) { return toStr(obj) === '[object Date]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
217+
function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
218+
function isError(obj) { return toStr(obj) === '[object Error]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
219+
function isString(obj) { return toStr(obj) === '[object String]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
220+
function isNumber(obj) { return toStr(obj) === '[object Number]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
221+
function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!hasToStringTag || !(Symbol.toStringTag in obj)); }
222+
// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives
217223
function isSymbol(obj) { return toStr(obj) === '[object Symbol]'; }
218-
function isString(obj) { return toStr(obj) === '[object String]'; }
219-
function isNumber(obj) { return toStr(obj) === '[object Number]'; }
220224
function isBigInt(obj) { return toStr(obj) === '[object BigInt]'; }
221-
function isBoolean(obj) { return toStr(obj) === '[object Boolean]'; }
222225

223226
var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };
224227
function has(obj, key) {

test/fakes.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
var inspect = require('../');
4+
var test = require('tape');
5+
var hasSymbols = require('has-symbols')();
6+
var forEach = require('for-each');
7+
8+
test('fakes', { skip: !hasSymbols || typeof Symbol.toStringTag !== 'symbol' }, function (t) {
9+
forEach([
10+
'Array',
11+
'Boolean',
12+
'Date',
13+
'Error',
14+
'Number',
15+
'RegExp',
16+
'String'
17+
], function (expected) {
18+
var faker = {};
19+
faker[Symbol.toStringTag] = expected;
20+
21+
t.equal(
22+
inspect(faker),
23+
'{ [Symbol(Symbol.toStringTag)]: \'' + expected + '\' }',
24+
'faker masquerading as ' + expected + ' is not shown as one'
25+
);
26+
});
27+
28+
t.end();
29+
});

0 commit comments

Comments
 (0)