eelcocramer / node-bluetooth-serial-port

Serial I/O over bluetooth for NodeJS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

osx: buffer overflow when data.length > 1024

mackwic opened this issue · comments

Related issue: #74

So, after some more digging, it seems that the segfaults could also come from an overflow of the reception buffer. This is osx specific, linux and windows are protected.

Here is the linux implem:

// read directly from the rfcomm socket, protected by the last argument
// ssize_t read(int fildes, void *buf, size_t nbyte);
baton->size = read(baton->rfcomm->s, buf, sizeof(buf));

Windows is roughly similar:

// read directly from the rfcomm socket. Protected by the len argument
// int recv(  _In_  SOCKET s,  _Out_ char   *buf,  _In_  int    len,  _In_  int    flags);
baton->size = recv(baton->rfcomm->s, (char *)buf, _countof(buf), 0);

And the osx one:

// size_t pipe_pop_eager(pipe_consumer_t* p, void* target, size_t count)
size = pipe_pop_eager(baton->rfcomm->consumer, buf, sizeof(buf));

Seems the same, BUT it's the read from the queue. What about the read from the socket ?
It's here:

NSData *data = [NSData dataWithBytes: dataPointer length: dataLength];

if (res != NULL && res.producer != NULL) {
    // push the data into the pipe so it can be read from the main thread
    pipe_push(res.producer, [data bytes], data.length);
}

So, I didn't found the place where this callback is setup, which is sad (if you can help me on that I would be glad), but I know for a fact that the length of the data pushed in the pipe is not checked.
Which means that we can (and will) push data with size > 1024, which ends to bad things. I am pretty sure there's a buffer overflow implied somewhere.

The fix could be:

  • trash any data which size > 1024
  • trim the data to 1024
  • split the data in frames of 1024, which would be the most consistent behavior. I dont know if it's feasible with this implementation of queue. Should be.
commented

The callback is setup here by setting the delegate object for the connection to self.

The pipe_pop_eager function tries to pop up to sizeof(buf) elements from the pipe. If there are more elements it will not pop them (until the next iteration). So I do not believe this is causing your problem.

From the docs of pipe_pop_eager:

/*
 * Tries to pop `count' elements out of the pipe and into `target', returning
 * the number of elements successfully copied. This function will block until:
 *
 * a) there is at least one element in the pipe.
 * b) all producer_t handles have been freed (including the parent pipe_t).
 *
 * If this function returns 0, there will be no more elements coming in. Every
 * subsequent call will return 0.
 *
 * The difference between this function and pipe_pop is that this one will
 * return as soon as any elements are available, whereas pipe_pop will do its
 * best to fill `target' first.
 */

Yes, thanks for the clarification. I definitely get segfaults when the size is > 1024. I will continue to dig deeper, then. :)