Version
v24.18.0
Platform
Linux scatha 7.0.11-76070011-generic #202606011647~1780583630~22.04~70ad774 SMP PREEMPT_DYNAMIC Thu J x86_64 x86_64 x86_64 GNU/Linux
Subsystem
lib/internal/tls/wrap.js
What steps will reproduce the bug?
Very minimal (and artificial):
constnet=require('net');consts=newnet.Socket();s._parent=undefined;// a chain link left `undefined` (see note on the trigger)s._unrefTimer();More representative, though the real case involved some library setting the handle to undefined whereas this does it explicitly:
constfs=require('fs');consttls=require('tls');// self-signed cert: openssl req -x509 -newkey rsa:2048 -nodes \// -keyout key.pem -out cert.pem -days 2 -subj "/CN=localhost"constopts={key: fs.readFileSync('key.pem'),cert: fs.readFileSync('cert.pem')};constserver=tls.createServer(opts,(conn)=>{setTimeout(()=>conn.write('x'),50);// inbound record after the chain is corrupted});server.listen(0,()=>{constclient=tls.connect({port: server.address().port,rejectUnauthorized: false},()=>{client._parent=undefined;},// invariant violation (stands in for teardown race));client.on('error',()=>{});});How often does it reproduce? Is there a required condition?
It seems to happen very sporadically; we're seeing a few instances a day in a system that handles significant volume.
What is the expected behavior? Why is that the expected behavior?
The object should be unref-ed, and with no parent, the parent traversal should be a no-op.
What do you see instead?
TypeError: Cannot read properties of undefined (reading 'Symbol(timeout)')
at TLSSocket._unrefTimer (node:net:529:10)
at TLSWrap.onStreamRead (node:internal/stream_base_commons:172:23)
Additional information
In lib/net.js, the parent chain is traversed with an exact equality check s !== null which fails if some library happens to null out the parent ref with undefined, instead. If this were a lax (s != null) check, the error ought to go away.
const{ kTimeout }=require('internal/timers');// kTimeout = Symbol('timeout')Socket.prototype._unrefTimer=function_unrefTimer(){for(lets=this;s!==null;s=s._parent){if(s[kTimeout])s[kTimeout].refresh();}};
Version
v24.18.0
Platform
Subsystem
lib/internal/tls/wrap.js
What steps will reproduce the bug?
Very minimal (and artificial):
More representative, though the real case involved some library setting the handle to
undefinedwhereas this does it explicitly:How often does it reproduce? Is there a required condition?
It seems to happen very sporadically; we're seeing a few instances a day in a system that handles significant volume.
What is the expected behavior? Why is that the expected behavior?
The object should be unref-ed, and with no parent, the parent traversal should be a no-op.
What do you see instead?
Additional information
In
lib/net.js, the parent chain is traversed with an exact equality checks !== nullwhich fails if some library happens to null out the parent ref withundefined, instead. If this were a lax (s != null) check, the error ought to go away.