From 7d1d7390ebef3d8a6b27d9be8a597d423e46f2cc Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 8 Dec 2017 15:33:41 +0100 Subject: [PATCH] src: fix inspector nullptr deref on abrupt exit Fix a nullptr dereference on abrupt termination when async call stack recording is enabled. Bug discovered while trying to write a regression test for the bug fix in commit df79b7d821 ("src: fix missing handlescope bug in inspector".) PR-URL: https://github.com/nodejs/node/pull/17577 Reviewed-By: Anna Henningsen Reviewed-By: Timothy Gu Reviewed-By: Colin Ihrig Reviewed-By: Refael Ackermann Reviewed-By: Eugene Ostroukhov --- src/inspector_agent.cc | 10 +++--- .../test-inspector-async-call-stack-abort.js | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 test/sequential/test-inspector-async-call-stack-abort.js diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 216b43ca6c3379..95e1d642915b5c 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -325,10 +325,12 @@ class NodeInspectorClient : public V8InspectorClient { } void maxAsyncCallStackDepthChanged(int depth) override { - if (depth == 0) { - env_->inspector_agent()->DisableAsyncHook(); - } else { - env_->inspector_agent()->EnableAsyncHook(); + if (auto agent = env_->inspector_agent()) { + if (depth == 0) { + agent->DisableAsyncHook(); + } else { + agent->EnableAsyncHook(); + } } } diff --git a/test/sequential/test-inspector-async-call-stack-abort.js b/test/sequential/test-inspector-async-call-stack-abort.js new file mode 100644 index 00000000000000..1ec46ab3cfeb9d --- /dev/null +++ b/test/sequential/test-inspector-async-call-stack-abort.js @@ -0,0 +1,34 @@ +// Check that abrupt termination when async call stack recording is enabled +// does not segfault the process. +'use strict'; +const common = require('../common'); +common.skipIfInspectorDisabled(); +common.skipIf32Bits(); + +const { strictEqual } = require('assert'); +const eyecatcher = 'nou, houdoe he?'; + +if (process.argv[2] === 'child') { + const { Session } = require('inspector'); + const { promisify } = require('util'); + const { registerAsyncHook } = process.binding('inspector'); + (async () => { + let enabled = 0; + registerAsyncHook(() => ++enabled, () => {}); + const session = new Session(); + session.connect(); + session.post = promisify(session.post); + await session.post('Debugger.enable'); + strictEqual(enabled, 0); + await session.post('Debugger.setAsyncCallStackDepth', { maxDepth: 42 }); + strictEqual(enabled, 1); + throw new Error(eyecatcher); + })(); +} else { + const { spawnSync } = require('child_process'); + const options = { encoding: 'utf8' }; + const proc = spawnSync(process.execPath, [__filename, 'child'], options); + strictEqual(proc.status, 0); + strictEqual(proc.signal, null); + strictEqual(proc.stderr.includes(eyecatcher), true); +}