From 5541fbab6731413a45b98956569f2f37309f70d4 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Mon, 9 Jan 2023 16:30:40 +0100 Subject: [PATCH 1/5] improve performance on SyntaxErrors --- benchmarks/throw.js | 8 ++++---- index.js | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/benchmarks/throw.js b/benchmarks/throw.js index 235da29..c84ba6a 100755 --- a/benchmarks/throw.js +++ b/benchmarks/throw.js @@ -11,7 +11,7 @@ const internals = { const suite = new Benchmark.Suite() suite - .add('JSON.parse', () => { + .add('JSON.parse valid', () => { JSON.parse(internals.text) }) .add('JSON.parse error', () => { @@ -21,15 +21,15 @@ suite }) .add('secure-json-parse parse', () => { try { - sjson.parse(internals.text) + sjson.parse(internals.invalid) } catch (ignoreErr) { } }) .add('secure-json-parse safeParse', () => { - sjson.safeParse(internals.text) + sjson.safeParse(internals.invalid) }) .add('reviver', () => { try { - JSON.parse(internals.text, internals.reviver) + JSON.parse(internals.invalid, internals.reviver) } catch (ignoreErr) { } }) .on('cycle', (event) => { diff --git a/index.js b/index.js index 99113a1..cd2de5b 100755 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const hasBuffer = typeof Buffer !== 'undefined' const suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/ const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/ -function parse (text, reviver, options) { +function _parse (text, reviver, options) { // Normalize arguments if (options == null) { if (reviver !== null && typeof reviver === 'object') { @@ -97,9 +97,19 @@ function filter (obj, { protoAction = 'error', constructorAction = 'error', safe return obj } +function parse (text, reviver, options) { + Error.stackTraceLimit = 0 + const result = _parse(text, reviver, options) + Error.stackTraceLimit = 10 + return result +} + function safeParse (text, reviver) { try { - return parse(text, reviver, { safe: true }) + Error.stackTraceLimit = 0 + const result = _parse(text, reviver, { safe: true }) + Error.stackTraceLimit = 10 + return result } catch (ignoreError) { return null } From b266a449237c82fa6e01b42dbebb09e5cd38bea4 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Mon, 9 Jan 2023 23:11:09 +0100 Subject: [PATCH 2/5] add unit test --- test/index.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/index.test.js b/test/index.test.js index 4c6ac8a..8ed5ef5 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -145,6 +145,14 @@ test('parse', t => { t.end() }) + t.test('should reset stackTraceLimit', t => { + const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }' + Error.stackTraceLimit = 42 + t.throws(() => j.parse(text)) + t.same(Error.stackTraceLimit, 42) + t.end() + }) + t.end() }) @@ -372,6 +380,14 @@ test('safeParse', t => { t.end() }) + t.test('should reset stackTraceLimit', t => { + const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }' + Error.stackTraceLimit = 42 + t.same(j.safeParse(text), null) + t.same(Error.stackTraceLimit, 42) + t.end() + }) + t.test('sanitizes nested object string', t => { const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }' From a2e9de81b00d829d95bfc5842276a860b3ccda8d Mon Sep 17 00:00:00 2001 From: uzlopak Date: Mon, 9 Jan 2023 23:11:51 +0100 Subject: [PATCH 3/5] fix resetting stackTraceLimit --- index.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index cd2de5b..292ff70 100755 --- a/index.js +++ b/index.js @@ -98,19 +98,27 @@ function filter (obj, { protoAction = 'error', constructorAction = 'error', safe } function parse (text, reviver, options) { - Error.stackTraceLimit = 0 - const result = _parse(text, reviver, options) - Error.stackTraceLimit = 10 - return result + const stackTraceLimit = Error.stackTraceLimit + try { + Error.stackTraceLimit = 0 + const result = _parse(text, reviver, options) + Error.stackTraceLimit = stackTraceLimit + return result + } catch (e) { + Error.stackTraceLimit = stackTraceLimit + throw e + } } function safeParse (text, reviver) { + const stackTraceLimit = Error.stackTraceLimit try { Error.stackTraceLimit = 0 const result = _parse(text, reviver, { safe: true }) - Error.stackTraceLimit = 10 + Error.stackTraceLimit = stackTraceLimit return result - } catch (ignoreError) { + } catch (ignoredError) { + Error.stackTraceLimit = stackTraceLimit return null } } From 6213be97d2f2fba757677b75de82feb9c42c29f5 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Mon, 9 Jan 2023 23:33:02 +0100 Subject: [PATCH 4/5] fix lnt error --- test/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.test.js b/test/index.test.js index 8ed5ef5..564f764 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -152,7 +152,7 @@ test('parse', t => { t.same(Error.stackTraceLimit, 42) t.end() }) - + t.end() }) From 36d07c2fd97dfdff86589ac9818067d85472f15b Mon Sep 17 00:00:00 2001 From: uzlopak Date: Tue, 10 Jan 2023 15:02:22 +0100 Subject: [PATCH 5/5] use finally block more efficiently --- index.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 292ff70..6d2fcc9 100755 --- a/index.js +++ b/index.js @@ -99,27 +99,23 @@ function filter (obj, { protoAction = 'error', constructorAction = 'error', safe function parse (text, reviver, options) { const stackTraceLimit = Error.stackTraceLimit + Error.stackTraceLimit = 0 try { - Error.stackTraceLimit = 0 - const result = _parse(text, reviver, options) + return _parse(text, reviver, options) + } finally { Error.stackTraceLimit = stackTraceLimit - return result - } catch (e) { - Error.stackTraceLimit = stackTraceLimit - throw e } } function safeParse (text, reviver) { const stackTraceLimit = Error.stackTraceLimit + Error.stackTraceLimit = 0 try { - Error.stackTraceLimit = 0 - const result = _parse(text, reviver, { safe: true }) - Error.stackTraceLimit = stackTraceLimit - return result - } catch (ignoredError) { - Error.stackTraceLimit = stackTraceLimit + return _parse(text, reviver, { safe: true }) + } catch (_e) { return null + } finally { + Error.stackTraceLimit = stackTraceLimit } }