1'use strict'; 2const common = require('../common'); 3if (!common.hasCrypto) 4 common.skip('missing crypto'); 5 6const assert = require('assert'); 7const tls = require('tls'); 8const net = require('net'); 9const fixtures = require('../common/fixtures'); 10 11// Regression test for https://github.com/nodejs/node/issues/8074 12// 13// This test has a dependency on the order in which the TCP connection is made, 14// and TLS server handshake completes. It assumes those server side events occur 15// before the client side write callback, which is not guaranteed by the TLS 16// API. It usually passes with TLS1.3, but TLS1.3 didn't exist at the time the 17// bug existed. 18// 19// Pin the test to TLS1.2, since the test shouldn't be changed in a way that 20// doesn't trigger a segfault in Node.js 7.7.3: 21// https://github.com/nodejs/node/issues/13184#issuecomment-303700377 22tls.DEFAULT_MAX_VERSION = 'TLSv1.2'; 23 24const key = fixtures.readKey('agent2-key.pem'); 25const cert = fixtures.readKey('agent2-cert.pem'); 26 27let tlsSocket; 28// tls server 29const tlsServer = tls.createServer({ cert, key }, (socket) => { 30 tlsSocket = socket; 31 socket.on('error', common.mustCall((error) => { 32 assert.strictEqual(error.code, 'EINVAL'); 33 tlsServer.close(); 34 netServer.close(); 35 })); 36}); 37 38let netSocket; 39// plain tcp server 40const netServer = net.createServer((socket) => { 41 // If client wants to use tls 42 tlsServer.emit('connection', socket); 43 44 netSocket = socket; 45}).listen(0, common.mustCall(function() { 46 connectClient(netServer); 47})); 48 49function connectClient(server) { 50 const tlsConnection = tls.connect({ 51 host: 'localhost', 52 port: server.address().port, 53 rejectUnauthorized: false 54 }); 55 56 tlsConnection.write('foo', 'utf8', common.mustCall(() => { 57 assert(netSocket); 58 netSocket.setTimeout(common.platformTimeout(10), common.mustCall(() => { 59 assert(tlsSocket); 60 // This breaks if TLSSocket is already managing the socket: 61 netSocket.destroy(); 62 const interval = setInterval(() => { 63 // Checking this way allows us to do the write at a time that causes a 64 // segmentation fault (not always, but often) in Node.js 7.7.3 and 65 // earlier. If we instead, for example, wait on the `close` event, then 66 // it will not segmentation fault, which is what this test is all about. 67 if (tlsSocket._handle._parent.bytesRead === 0) { 68 tlsSocket.write('bar'); 69 clearInterval(interval); 70 } 71 }, 1); 72 })); 73 })); 74 tlsConnection.on('error', (e) => { 75 // Tolerate the occasional ECONNRESET. 76 // Ref: https://github.com/nodejs/node/issues/13184 77 if (e.code !== 'ECONNRESET') 78 throw e; 79 }); 80} 81