Spaces:
Sleeping
Sleeping
File size: 2,122 Bytes
4cadbaf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
'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;
}
};
|