@@ -8385,10 +8385,10 @@ function encode (obj, opt) {
83858385 if (typeof opt === 'string') {
83868386 opt = {
83878387 section: opt,
8388- whitespace: false
8388+ whitespace: false,
83898389 };
83908390 } else {
8391- opt = opt || {} ;
8391+ opt = opt || Object.create(null) ;
83928392 opt.whitespace = opt.whitespace === true;
83938393 }
83948394
@@ -8400,27 +8400,25 @@ function encode (obj, opt) {
84008400 val.forEach(function (item) {
84018401 out += safe(k + '[]') + separator + safe(item) + '\n';
84028402 });
8403- } else if (val && typeof val === 'object') {
8403+ } else if (val && typeof val === 'object')
84048404 children.push(k);
8405- } else {
8405+ else
84068406 out += safe(k) + separator + safe(val) + eol;
8407- }
84088407 });
84098408
8410- if (opt.section && out.length) {
8409+ if (opt.section && out.length)
84118410 out = '[' + safe(opt.section) + ']' + eol + out;
8412- }
84138411
84148412 children.forEach(function (k, _, __) {
84158413 var nk = dotSplit(k).join('\\.');
84168414 var section = (opt.section ? opt.section + '.' : '') + nk;
84178415 var child = encode(obj[k], {
84188416 section: section,
8419- whitespace: opt.whitespace
8417+ whitespace: opt.whitespace,
84208418 });
8421- if (out.length && child.length) {
8419+ if (out.length && child.length)
84228420 out += eol;
8423- }
8421+
84248422 out += child;
84258423 });
84268424
@@ -8432,28 +8430,38 @@ function dotSplit (str) {
84328430 .replace(/\\\./g, '\u0001')
84338431 .split(/\./).map(function (part) {
84348432 return part.replace(/\1/g, '\\.')
8435- .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001')
8433+ .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001')
84368434 })
84378435}
84388436
84398437function decode (str) {
8440- var out = {} ;
8438+ var out = Object.create(null) ;
84418439 var p = out;
84428440 var section = null;
84438441 // section |key = value
84448442 var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i;
84458443 var lines = str.split(/[\r\n]+/g);
84468444
84478445 lines.forEach(function (line, _, __) {
8448- if (!line || line.match(/^\s*[;#]/)) return
8446+ if (!line || line.match(/^\s*[;#]/))
8447+ return
84498448 var match = line.match(re);
8450- if (!match) return
8449+ if (!match)
8450+ return
84518451 if (match[1] !== undefined) {
84528452 section = unsafe(match[1]);
8453- p = out[section] = out[section] || {};
8453+ if (section === '__proto__') {
8454+ // not allowed
8455+ // keep parsing the section, but don't attach it.
8456+ p = Object.create(null);
8457+ return
8458+ }
8459+ p = out[section] = out[section] || Object.create(null);
84548460 return
84558461 }
84568462 var key = unsafe(match[2]);
8463+ if (key === '__proto__')
8464+ return
84578465 var value = match[3] ? unsafe(match[4]) : true;
84588466 switch (value) {
84598467 case 'true':
@@ -8464,43 +8472,46 @@ function decode (str) {
84648472 // Convert keys with '[]' suffix to an array
84658473 if (key.length > 2 && key.slice(-2) === '[]') {
84668474 key = key.substring(0, key.length - 2);
8467- if (!p[key]) {
8475+ if (key === '__proto__')
8476+ return
8477+ if (!p[key])
84688478 p[key] = [];
8469- } else if (!Array.isArray(p[key])) {
8479+ else if (!Array.isArray(p[key]))
84708480 p[key] = [p[key]];
8471- }
84728481 }
84738482
84748483 // safeguard against resetting a previously defined
84758484 // array by accidentally forgetting the brackets
8476- if (Array.isArray(p[key])) {
8485+ if (Array.isArray(p[key]))
84778486 p[key].push(value);
8478- } else {
8487+ else
84798488 p[key] = value;
8480- }
84818489 });
84828490
84838491 // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
84848492 // use a filter to return the keys that have to be deleted.
84858493 Object.keys(out).filter(function (k, _, __) {
84868494 if (!out[k] ||
84878495 typeof out[k] !== 'object' ||
8488- Array.isArray(out[k])) {
8496+ Array.isArray(out[k]))
84898497 return false
8490- }
8498+
84918499 // see if the parent section is also an object.
84928500 // if so, add it to that, and mark this one for deletion
84938501 var parts = dotSplit(k);
84948502 var p = out;
84958503 var l = parts.pop();
84968504 var nl = l.replace(/\\\./g, '.');
84978505 parts.forEach(function (part, _, __) {
8498- if (!p[part] || typeof p[part] !== 'object') p[part] = {};
8506+ if (part === '__proto__')
8507+ return
8508+ if (!p[part] || typeof p[part] !== 'object')
8509+ p[part] = Object.create(null);
84998510 p = p[part];
85008511 });
8501- if (p === out && nl === l) {
8512+ if (p === out && nl === l)
85028513 return false
8503- }
8514+
85048515 p[nl] = out[k];
85058516 return true
85068517 }).forEach(function (del, _, __) {
@@ -8522,42 +8533,43 @@ function safe (val) {
85228533 (val.length > 1 &&
85238534 isQuoted(val)) ||
85248535 val !== val.trim())
8525- ? JSON.stringify(val)
8526- : val.replace(/;/g, '\\;').replace(/#/g, '\\#')
8536+ ? JSON.stringify(val)
8537+ : val.replace(/;/g, '\\;').replace(/#/g, '\\#')
85278538}
85288539
85298540function unsafe (val, doUnesc) {
85308541 val = (val || '').trim();
85318542 if (isQuoted(val)) {
85328543 // remove the single quotes before calling JSON.parse
8533- if (val.charAt(0) === "'") {
8544+ if (val.charAt(0) === "'")
85348545 val = val.substr(1, val.length - 2);
8535- }
8536- try { val = JSON.parse(val); } catch (_) {}
8546+
8547+ try {
8548+ val = JSON.parse(val);
8549+ } catch (_) {}
85378550 } else {
85388551 // walk the val to find the first not-escaped ; character
85398552 var esc = false;
85408553 var unesc = '';
85418554 for (var i = 0, l = val.length; i < l; i++) {
85428555 var c = val.charAt(i);
85438556 if (esc) {
8544- if ('\\;#'.indexOf(c) !== -1) {
8557+ if ('\\;#'.indexOf(c) !== -1)
85458558 unesc += c;
8546- } else {
8559+ else
85478560 unesc += '\\' + c;
8548- }
8561+
85498562 esc = false;
8550- } else if (';#'.indexOf(c) !== -1) {
8563+ } else if (';#'.indexOf(c) !== -1)
85518564 break
8552- } else if (c === '\\') {
8565+ else if (c === '\\')
85538566 esc = true;
8554- } else {
8567+ else
85558568 unesc += c;
8556- }
85578569 }
8558- if (esc) {
8570+ if (esc)
85598571 unesc += '\\';
8560- }
8572+
85618573 return unesc.trim()
85628574 }
85638575 return val
0 commit comments