You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.1 KiB
98 lines
2.1 KiB
4 years ago
|
'use strict';
|
||
|
|
||
|
|
||
|
const internals = {
|
||
|
suspectRx: /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*\:/
|
||
|
};
|
||
|
|
||
|
|
||
|
exports.parse = function (text, reviver, options) {
|
||
|
|
||
|
// Normalize arguments
|
||
|
|
||
|
if (!options) {
|
||
|
if (reviver &&
|
||
|
typeof reviver === 'object') {
|
||
|
|
||
|
options = reviver;
|
||
|
reviver = undefined;
|
||
|
}
|
||
|
else {
|
||
|
options = {};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Parse normally, allowing exceptions
|
||
|
|
||
|
const obj = JSON.parse(text, reviver);
|
||
|
|
||
|
// options.protoAction: 'error' (default) / 'remove' / 'ignore'
|
||
|
|
||
|
if (options.protoAction === 'ignore') {
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
// Ignore null and non-objects
|
||
|
|
||
|
if (!obj ||
|
||
|
typeof obj !== 'object') {
|
||
|
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
// Check original string for potential exploit
|
||
|
|
||
|
if (!text.match(internals.suspectRx)) {
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
// Scan result for proto keys
|
||
|
|
||
|
exports.scan(obj, options);
|
||
|
|
||
|
return obj;
|
||
|
};
|
||
|
|
||
|
|
||
|
exports.scan = function (obj, options) {
|
||
|
|
||
|
options = options || {};
|
||
|
|
||
|
let next = [obj];
|
||
|
|
||
|
while (next.length) {
|
||
|
const nodes = next;
|
||
|
next = [];
|
||
|
|
||
|
for (const node of nodes) {
|
||
|
if (Object.prototype.hasOwnProperty.call(node, '__proto__')) { // Avoid calling node.hasOwnProperty directly
|
||
|
if (options.protoAction !== 'remove') {
|
||
|
throw new SyntaxError('Object contains forbidden prototype property');
|
||
|
}
|
||
|
|
||
|
delete node.__proto__;
|
||
|
}
|
||
|
|
||
|
for (const key in node) {
|
||
|
const value = node[key];
|
||
|
if (value &&
|
||
|
typeof value === 'object') {
|
||
|
|
||
|
next.push(node[key]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
exports.safeParse = function (text, reviver) {
|
||
|
|
||
|
try {
|
||
|
return exports.parse(text, reviver);
|
||
|
}
|
||
|
catch (ignoreError) {
|
||
|
return null;
|
||
|
}
|
||
|
};
|