Skip to content

Commit 032fbaf

Browse files
committed
Use Object.create(null) to avoid default object property hazards
1 parent 2da9039 commit 032fbaf

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

ini.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function encode (obj, opt) {
1818
whitespace: false
1919
}
2020
} else {
21-
opt = opt || {}
21+
opt = opt || Object.create(null)
2222
opt.whitespace = opt.whitespace === true
2323
}
2424

@@ -67,7 +67,7 @@ function dotSplit (str) {
6767
}
6868

6969
function decode (str) {
70-
var out = {}
70+
var out = Object.create(null)
7171
var p = out
7272
var section = null
7373
// section |key = value
@@ -83,13 +83,14 @@ function decode (str) {
8383
if (section === '__proto__') {
8484
// not allowed
8585
// keep parsing the section, but don't attach it.
86-
p = {}
86+
p = Object.create(null)
8787
return
8888
}
89-
p = out[section] = out[section] || {}
89+
p = out[section] = out[section] || Object.create(null)
9090
return
9191
}
9292
var key = unsafe(match[2])
93+
if (key === '__proto__') return
9394
var value = match[3] ? unsafe(match[4]) : true
9495
switch (value) {
9596
case 'true':
@@ -133,7 +134,7 @@ function decode (str) {
133134
var nl = l.replace(/\\\./g, '.')
134135
parts.forEach(function (part, _, __) {
135136
if (part === '__proto__') return
136-
if (!p[part] || typeof p[part] !== 'object') p[part] = {}
137+
if (!p[part] || typeof p[part] !== 'object') p[part] = Object.create(null)
137138
p = p[part]
138139
})
139140
if (p === out && nl === l) {

test/proto.js

+27-14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var t = require('tap')
33

44
var data = `
55
__proto__ = quux
6+
constructor.prototype.foo = asdfasdf
67
foo = baz
78
[__proto__]
89
foo = bar
@@ -15,27 +16,39 @@ hello = snyk
1516
__proto__[] = you did a good job
1617
__proto__[] = so you deserve arrays
1718
thanks = true
19+
[ctor.constructor.prototype]
20+
foo = asdfasdf
1821
`
22+
1923
var res = ini.parse(data)
20-
t.deepEqual(res, {
24+
25+
t.deepEqual(res, Object.assign(Object.create(null), {
26+
'constructor.prototype.foo': 'asdfasdf',
2127
foo: 'baz',
22-
other: {
28+
other: Object.assign(Object.create(null), {
2329
foo: 'asdf',
24-
},
25-
kid: {
26-
foo: {
30+
}),
31+
kid: Object.assign(Object.create(null), {
32+
foo: Object.assign(Object.create(null), {
2733
foo: 'kid',
28-
},
29-
},
30-
arrproto: {
34+
}),
35+
}),
36+
arrproto: Object.assign(Object.create(null), {
3137
hello: 'snyk',
3238
thanks: true,
33-
},
34-
})
35-
t.equal(res.__proto__, Object.prototype)
36-
t.equal(res.kid.__proto__, Object.prototype)
37-
t.equal(res.kid.foo.__proto__, Object.prototype)
38-
t.equal(res.arrproto.__proto__, Object.prototype)
39+
}),
40+
ctor: Object.assign(Object.create(null), {
41+
constructor: Object.assign(Object.create(null), {
42+
prototype: Object.assign(Object.create(null), {
43+
foo: 'asdfasdf',
44+
}),
45+
}),
46+
}),
47+
}))
48+
t.equal(res.__proto__, undefined)
49+
t.equal(res.kid.__proto__, undefined)
50+
t.equal(res.kid.foo.__proto__, undefined)
51+
t.equal(res.arrproto.__proto__, undefined)
3952
t.equal(Object.prototype.foo, undefined)
4053
t.equal(Object.prototype[0], undefined)
4154
t.equal(Object.prototype['0'], undefined)

0 commit comments

Comments
 (0)