]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
liblldpctl: fix infinite loop when user is reading fixed chunks
authorPradosh Mohapatra <pmohapat@cumulusnetworks.com>
Fri, 7 Jun 2013 06:28:23 +0000 (08:28 +0200)
committerVincent Bernat <bernat@luffy.cx>
Fri, 7 Jun 2013 06:28:23 +0000 (08:28 +0200)
ISSUE:

_lldpctl_do_something() has the following loop for receiving a complete
message:

while ((bytes_needed = ctl_msg_recv_unserialized(...)) > 0) {
    _lldpctl_needs(bytes_needed)
}

ctl_msg_recv_unserialized() processes the received message and determines
how many more bytes are needed. First time, it requests "header" worth of
bytes. Once it receives that, it looks at header->len to determine next
set of bytes.

_lldpctl_needs() calls the connection's receive() routine to receive a
chunk of data and copies that over the a buffer in the connection structure,
either by malloc/copy or realloc/memmove. This buffer is called
conn->input_buffer. conn->input_buffer_len stores how many bytes are
currently in conn->input_buffer.

The issue is with the following statement in _lldpctl_needs():

        if (conn->input_buffer_len >= length) return 0;

where length is bytes_needed in the above illustration.

Suppose the message requires 16578 bytes. The connection's receive()
routine provided by the application reads in chunks of 1024 bytes.
With the above logic, the loop will execute successfully for 16 times
with the following resultant state:

conn->input_buffer_len = 16384
bytes_needed = 194

The above conditional statement in the beginning of _lldpctl_needs()
will cause it to return 0. ctl_msg_recv_unserialized() will keep asking
for 194 more bytes. The while() loop goes ad infinitum.

PATCH:

Remove the above statement. It is not needed.

src/lib/connection.c

index 2fe7c44d6c0dbf4582a8b16a60dfda21c7a6a42a..a5baeaf5283d61cfe32fbd896b6f0c789ec6a9a5 100644 (file)
@@ -157,7 +157,6 @@ _lldpctl_needs(lldpctl_conn_t *conn, size_t length)
 {
        uint8_t *buffer = NULL;
        ssize_t  rc;
-       if (conn->input_buffer_len >= length) return 0;
 
        if ((buffer = malloc(length)) == NULL)
                return SET_ERROR(conn, LLDPCTL_ERR_NOMEM);