diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 869bbda42f7898..9ecd92021de17f 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -689,7 +689,9 @@ TLSSocket.prototype._init = function(socket, wrap) { if (event !== 'keylog') return; - ssl.enableKeylogCallback(); + // Guard against enableKeylogCallback after destroy + if (!this._handle) return; + this._handle.enableKeylogCallback(); // Remove this listener since it's no longer needed. this.removeListener('newListener', keylogNewListener); @@ -733,7 +735,9 @@ TLSSocket.prototype._init = function(socket, wrap) { if (event !== 'session') return; - ssl.enableSessionCallbacks(); + // Guard against enableSessionCallbacks after destroy + if (!this._handle) return; + this._handle.enableSessionCallbacks(); // Remove this listener since it's no longer needed. this.removeListener('newListener', newListener); diff --git a/test/parallel/test-tls-tlswrap-segfault-2.js b/test/parallel/test-tls-tlswrap-segfault-2.js new file mode 100644 index 00000000000000..d4f3b12b99fdd5 --- /dev/null +++ b/test/parallel/test-tls-tlswrap-segfault-2.js @@ -0,0 +1,22 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +// This test ensures that Node.js doesn't incur a segfault while +// adding session or keylog listeners after destroy. +// https://github.com/nodejs/node/issues/38133 +// https://github.com/nodejs/node/issues/38135 + +const tls = require('tls'); +const tlsSocketKeyLog = tls.connect('cause-error'); +tlsSocketKeyLog.on('error', common.mustCall()); +tlsSocketKeyLog.on('close', common.mustCall(() => { + tlsSocketKeyLog.on('keylog', common.mustNotCall()); +})); + +const tlsSocketSession = tls.connect('cause-error-2'); +tlsSocketSession.on('error', common.mustCall()); +tlsSocketSession.on('close', common.mustCall(() => { + tlsSocketSession.on('session', common.mustNotCall()); +}));