Skip to content

Possible Nan::Callback leak in read() on a closed connection #490

Description

@OvOhao

Possible Nan::Callback leak in read() on a closed connection

I found a possible native heap leak in BTSerialPortBinding::Read. On the
closed-connection branch it allocates a Nan::Callback, calls it synchronously, and
never deletes it. The same code is present on both the Linux and Windows bindings.

Files: src/linux/BTSerialPortBinding.cc, src/windows/BTSerialPortBinding.cc

Function: BTSerialPortBinding::Read

// callback with an error if the connection has been closed.
if (rfcomm->s == 0) {
    Local<Value> argv[2];
    argv[0] = Nan::Error("The connection has been closed");
    argv[1] = Nan::Undefined();

    Nan::AsyncResource resource("bluetooth-serial-port:Read");
    Nan::Callback *nc = new Nan::Callback(cb);
    nc->Call(2, argv, &resource);          // nc is used but never deleted
} else {
    read_baton_t *baton = new read_baton_t();
    baton->rfcomm = rfcomm;
    baton->cb = new Nan::Callback(cb);
    baton->request.data = baton;
    baton->rfcomm->Ref();
    uv_queue_work(uv_default_loop(), &baton->request, EIO_Read, (uv_after_work_cb)EIO_AfterRead);
}

On the rfcomm->s == 0 branch, nc is a raw heap Nan::Callback (which holds a
v8::Persistent to the JS function). It is invoked synchronously but never deleted,
and unlike the else branch it is never handed to a worker that would free it. Each
read() on an already-closed connection leaks one Nan::Callback plus its retained
function reference — a common pattern is a read loop that keeps calling read() after
the peer disconnects, leaking once per call.

The project already knows the correct shape: the server variant handles the same
closed-connection branch with an owning smart pointer
(src/linux/BTSerialPortBindingServer.cc: std::unique_ptr<Nan::Callback> nc(new Nan::Callback(cb));).

Suggested fix: give nc the same ownership, e.g. std::unique_ptr<Nan::Callback> nc(new Nan::Callback(cb)); nc->Call(2, argv, &resource);, or delete nc; after the call.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions