]> git.meshlink.io Git - utcp/blobdiff - utcp.c
Fix check for return value of malloc(), allow initially zero length buffer.
[utcp] / utcp.c
diff --git a/utcp.c b/utcp.c
index 7624aa576d39c8753c810cea4c4f8643c377d3d4..9434c70170e5a6f9b9de5f0b8743e7fed9914223 100644 (file)
--- a/utcp.c
+++ b/utcp.c
@@ -130,16 +130,30 @@ static int32_t seqdiff(uint32_t a, uint32_t b) {
 // TODO: convert to ringbuffers to avoid memmove() operations.
 
 // Store data into the buffer
-static ssize_t buffer_put(struct buffer *buf, const void *data, size_t len) {
+static ssize_t buffer_put_at(struct buffer *buf, size_t offset, const void *data, size_t len) {
        if(buf->maxsize <= buf->used)
                return 0;
-       if(len > buf->maxsize - buf->used)
-               len = buf->maxsize - buf->used;
-       if(len > buf->size - buf->used) {
+
+       debug("buffer_put_at %zu %zu %zu\n", buf->used, offset, len);
+
+       size_t required = offset + len;
+       if(required > buf->maxsize) {
+               if(offset >= buf->maxsize)
+                       return 0;
+               abort();
+               len = buf->maxsize - offset;
+               required = buf->maxsize;
+       }
+
+       if(required > buf->size) {
                size_t newsize = buf->size;
-               do {
-                       newsize *= 2;
-               } while(newsize < buf->used + len);
+               if(!newsize) {
+                       newsize = required;
+               } else {
+                       do {
+                               newsize *= 2;
+                       } while(newsize < buf->used + len);
+               }
                if(newsize > buf->maxsize)
                        newsize = buf->maxsize;
                char *newdata = realloc(buf->data, newsize);
@@ -148,11 +162,17 @@ static ssize_t buffer_put(struct buffer *buf, const void *data, size_t len) {
                buf->data = newdata;
                buf->size = newsize;
        }
-       memcpy(buf->data + buf->used, data, len);
-       buf->used += len;
+
+       memcpy(buf->data + offset, data, len);
+       if(required > buf->used)
+               buf->used = required;
        return len;
 }
 
+static ssize_t buffer_put(struct buffer *buf, const void *data, size_t len) {
+       return buffer_put_at(buf, buf->used, data, len);
+}
+
 // Get data from the buffer. data can be NULL.
 static ssize_t buffer_get(struct buffer *buf, void *data, size_t len) {
        if(len > buf->used)
@@ -177,9 +197,11 @@ static ssize_t buffer_copy(struct buffer *buf, void *data, size_t offset, size_t
 
 static bool buffer_init(struct buffer *buf, uint32_t len, uint32_t maxlen) {
        memset(buf, 0, sizeof *buf);
-       buf->data = malloc(len);
-       if(!len)
-               return false;
+       if(len) {
+               buf->data = malloc(len);
+               if(!buf->data)
+                       return false;
+       }
        buf->size = len;
        buf->maxsize = maxlen;
        return true;
@@ -282,7 +304,12 @@ static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t s
 
        c->src = src;
        c->dst = dst;
+#ifdef UTCP_DEBUG
+#warning debugging
+       c->snd.iss = 0;
+#else
        c->snd.iss = rand();
+#endif
        c->snd.una = c->snd.iss;
        c->snd.nxt = c->snd.iss + 1;
        c->rcv.wnd = utcp->mtu;
@@ -360,7 +387,7 @@ static void ack(struct utcp_connection *c, bool sendatleastone) {
        } *pkt;
 
        pkt = malloc(sizeof pkt->hdr + c->utcp->mtu);
-       if(!pkt->data)
+       if(!pkt)
                return;
 
        pkt->hdr.src = c->src;