From 581b19a62d88f8a3c068b5a45f4542c2d6a495a5 Mon Sep 17 00:00:00 2001 From: James Crosby Date: Tue, 2 Mar 2021 16:49:26 +0000 Subject: [PATCH] use Object.create(null) to create all parsed objects (prevent prototype replacement) --- lib/parser.js | 10 +++++----- src/parser.coffee | 10 +++++----- test/parser.test.coffee | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index eda231cb..192382d3 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -141,14 +141,14 @@ this.saxParser.onopentag = (function(_this) { return function(node) { var key, newValue, obj, processedKey, ref; - obj = {}; + obj = Object.create(null); obj[charkey] = ""; if (!_this.options.ignoreAttrs) { ref = node.attributes; for (key in ref) { if (!hasProp.call(ref, key)) continue; if (!(attrkey in obj) && !_this.options.mergeAttrs) { - obj[attrkey] = {}; + obj[attrkey] = Object.create(null); } newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key]; processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key; @@ -226,7 +226,7 @@ } if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') { if (!_this.options.preserveChildrenOrder) { - node = {}; + node = Object.create(null); if (_this.options.attrkey in obj) { node[_this.options.attrkey] = obj[_this.options.attrkey]; delete obj[_this.options.attrkey]; @@ -241,7 +241,7 @@ obj = node; } else if (s) { s[_this.options.childkey] = s[_this.options.childkey] || []; - objClone = {}; + objClone = Object.create(null); for (key in obj) { if (!hasProp.call(obj, key)) continue; objClone[key] = obj[key]; @@ -258,7 +258,7 @@ } else { if (_this.options.explicitRoot) { old = obj; - obj = {}; + obj = Object.create(null); obj[nodeName] = old; } _this.resultObject = obj; diff --git a/src/parser.coffee b/src/parser.coffee index eb19c5b0..88ace67d 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -102,12 +102,12 @@ class exports.Parser extends events charkey = @options.charkey @saxParser.onopentag = (node) => - obj = {} + obj = Object.create(null) obj[charkey] = "" unless @options.ignoreAttrs for own key of node.attributes if attrkey not of obj and not @options.mergeAttrs - obj[attrkey] = {} + obj[attrkey] = Object.create(null) newValue = if @options.attrValueProcessors then processItem(@options.attrValueProcessors, node.attributes[key], key) else node.attributes[key] processedKey = if @options.attrNameProcessors then processItem(@options.attrNameProcessors, key) else key if @options.mergeAttrs @@ -163,7 +163,7 @@ class exports.Parser extends events # put children into property and unfold chars if necessary if @options.explicitChildren and not @options.mergeAttrs and typeof obj is 'object' if not @options.preserveChildrenOrder - node = {} + node = Object.create(null) # separate attributes if @options.attrkey of obj node[@options.attrkey] = obj[@options.attrkey] @@ -181,7 +181,7 @@ class exports.Parser extends events # append current node onto parent's array s[@options.childkey] = s[@options.childkey] or [] # push a clone so that the node in the children array can receive the #name property while the original obj can do without it - objClone = {} + objClone = Object.create(null) for own key of obj objClone[key] = obj[key] s[@options.childkey].push objClone @@ -198,7 +198,7 @@ class exports.Parser extends events if @options.explicitRoot # avoid circular references old = obj - obj = {} + obj = Object.create(null) obj[nodeName] = old @resultObject = obj diff --git a/test/parser.test.coffee b/test/parser.test.coffee index f2758759..796e2c69 100644 --- a/test/parser.test.coffee +++ b/test/parser.test.coffee @@ -547,13 +547,13 @@ module.exports = 'test single attrNameProcessors': skeleton(attrNameProcessors: [nameToUpperCase], (r)-> console.log 'Result object: ' + util.inspect r, false, 10 - equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAMELCASEATTR'), true - equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWERCASEATTR'), true) + equ {}.hasOwnProperty.call(r.sample.attrNameProcessTest[0].$, 'CAMELCASEATTR'), true + equ {}.hasOwnProperty.call(r.sample.attrNameProcessTest[0].$, 'LOWERCASEATTR'), true) 'test multiple attrNameProcessors': skeleton(attrNameProcessors: [nameToUpperCase, nameCutoff], (r)-> console.log 'Result object: ' + util.inspect r, false, 10 - equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('CAME'), true - equ r.sample.attrNameProcessTest[0].$.hasOwnProperty('LOWE'), true) + equ {}.hasOwnProperty.call(r.sample.attrNameProcessTest[0].$, 'CAME'), true + equ {}.hasOwnProperty.call(r.sample.attrNameProcessTest[0].$, 'LOWE'), true) 'test single attrValueProcessors': skeleton(attrValueProcessors: [nameToUpperCase], (r)-> console.log 'Result object: ' + util.inspect r, false, 10 @@ -575,21 +575,21 @@ module.exports = 'test single tagNameProcessors': skeleton(tagNameProcessors: [nameToUpperCase], (r)-> console.log 'Result object: ' + util.inspect r, false, 10 - equ r.hasOwnProperty('SAMPLE'), true - equ r.SAMPLE.hasOwnProperty('TAGNAMEPROCESSTEST'), true) + equ {}.hasOwnProperty.call(r, 'SAMPLE'), true + equ {}.hasOwnProperty.call(r.SAMPLE, 'TAGNAMEPROCESSTEST'), true) 'test single tagNameProcessors in simple callback': (test) -> fs.readFile fileName, (err, data) -> xml2js.parseString data, tagNameProcessors: [nameToUpperCase], (err, r)-> console.log 'Result object: ' + util.inspect r, false, 10 - equ r.hasOwnProperty('SAMPLE'), true - equ r.SAMPLE.hasOwnProperty('TAGNAMEPROCESSTEST'), true + equ {}.hasOwnProperty.call(r, 'SAMPLE'), true + equ {}.hasOwnProperty.call(r.SAMPLE, 'TAGNAMEPROCESSTEST'), true test.finish() 'test multiple tagNameProcessors': skeleton(tagNameProcessors: [nameToUpperCase, nameCutoff], (r)-> console.log 'Result object: ' + util.inspect r, false, 10 - equ r.hasOwnProperty('SAMP'), true - equ r.SAMP.hasOwnProperty('TAGN'), true) + equ {}.hasOwnProperty.call(r, 'SAMP'), true + equ {}.hasOwnProperty.call(r.SAMP, 'TAGN'), true) 'test attrValueProcessors key param': skeleton(attrValueProcessors: [replaceValueByName], (r)-> console.log 'Result object: ' + util.inspect r, false, 10