zhangjian
2023-06-05 0976d2d0f90cff460cedfdc8bd74e98c2c31a58c
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
'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;
    }
};