changeset 1057:16584026a1f0 nocircbuffer

allocate buffer and data in a single allocation
author Matt Johnston <matt@ucc.asn.au>
date Sun, 01 Mar 2015 21:16:09 +0800
parents a2bfd4374878
children 703c7cdd2577
files buffer.c buffer.h cli-agentfwd.c packet.c
diffstat 4 files changed, 40 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/buffer.c	Sun Mar 01 14:46:04 2015 +0800
+++ b/buffer.c	Sun Mar 01 21:16:09 2015 +0800
@@ -46,17 +46,15 @@
 		dropbear_exit("buf->size too big");
 	}
 
-	buf = (buffer*)m_malloc(sizeof(buffer));
+	buf = (buffer*)m_malloc(sizeof(buffer)+size);
 
 	if (size > 0) {
-		buf->data = (unsigned char*)m_malloc(size);
+		buf->data = (unsigned char*)buf + sizeof(buffer);
 	} else {
 		buf->data = NULL;
 	}
 
 	buf->size = size;
-	buf->pos = 0;
-	buf->len = 0;
 
 	return buf;
 
@@ -65,7 +63,6 @@
 /* free the buffer's data and the buffer itself */
 void buf_free(buffer* buf) {
 
-	m_free(buf->data)
 	m_free(buf);
 }
 
@@ -78,17 +75,18 @@
 
 /* resize a buffer, pos and len will be repositioned if required when
  * downsizing */
-void buf_resize(buffer *buf, unsigned int newsize) {
+buffer* buf_resize(buffer *buf, unsigned int newsize) {
 
 	if (newsize > BUF_MAX_SIZE) {
 		dropbear_exit("buf->size too big");
 	}
 
-	buf->data = m_realloc(buf->data, newsize);
+	buf = m_realloc(buf, sizeof(buffer)+newsize);
+	buf->data = (unsigned char*)buf + sizeof(buffer);
 	buf->size = newsize;
 	buf->len = MIN(newsize, buf->len);
 	buf->pos = MIN(newsize, buf->pos);
-
+	return buf;
 }
 
 /* Create a copy of buf, allocating required memory etc. */
@@ -227,15 +225,15 @@
 
 /* Return a string as a newly allocated buffer */
 buffer * buf_getstringbuf(buffer *buf) {
-	buffer *ret;
-	unsigned char* str;
-	unsigned int len;
-	str = buf_getstring(buf, &len);
-	ret = m_malloc(sizeof(*ret));
-	ret->data = str;
-	ret->len = len;
-	ret->size = len;
-	ret->pos = 0;
+	buffer *ret = NULL;
+	unsigned int len = buf_getint(buf);
+	if (len > MAX_STRING_LEN) {
+		dropbear_exit("String too long");
+	}
+	ret = buf_new(len);
+	memcpy(buf_getwriteptr(ret, len), buf_getptr(buf, len), len);
+	buf_incrpos(buf, len);
+	buf_incrlen(ret, len);
 	return ret;
 }
 
--- a/buffer.h	Sun Mar 01 14:46:04 2015 +0800
+++ b/buffer.h	Sun Mar 01 21:16:09 2015 +0800
@@ -29,7 +29,8 @@
 #include "includes.h"
 
 struct buf {
-
+	/* don't manipulate data member outside of buffer.c - it
+	is a pointer into the malloc holding buffer itself */
 	unsigned char * data;
 	unsigned int len; /* the used size */
 	unsigned int pos;
@@ -40,7 +41,8 @@
 typedef struct buf buffer;
 
 buffer * buf_new(unsigned int size);
-void buf_resize(buffer *buf, unsigned int newsize);
+/* Possibly returns a new buffer*, like realloc() */
+buffer * buf_resize(buffer *buf, unsigned int newsize);
 void buf_free(buffer* buf);
 void buf_burn(buffer* buf);
 buffer* buf_newcopy(buffer* buf);
--- a/cli-agentfwd.c	Sun Mar 01 14:46:04 2015 +0800
+++ b/cli-agentfwd.c	Sun Mar 01 21:16:09 2015 +0800
@@ -155,7 +155,7 @@
 		goto out;
 	}
 	
-	buf_resize(inbuf, readlen);
+	inbuf = buf_resize(inbuf, readlen);
 	buf_setpos(inbuf, 0);
 	ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen);
 	if ((size_t)ret != readlen) {
--- a/packet.c	Sun Mar 01 14:46:04 2015 +0800
+++ b/packet.c	Sun Mar 01 21:16:09 2015 +0800
@@ -257,7 +257,7 @@
 	}
 
 	if (len > ses.readbuf->size) {
-		buf_resize(ses.readbuf, len);		
+		ses.readbuf = buf_resize(ses.readbuf, len);		
 	}
 	buf_setlen(ses.readbuf, len);
 	buf_setpos(ses.readbuf, blocksize);
@@ -401,7 +401,7 @@
 				dropbear_exit("bad packet, oversized decompressed");
 			}
 			new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
-			buf_resize(ret, new_size);
+			ret = buf_resize(ret, new_size);
 		}
 	}
 }
@@ -640,7 +640,8 @@
 
 #ifndef DISABLE_ZLIB
 /* compresses len bytes from src, outputting to dest (starting from the
- * respective current positions. */
+ * respective current positions. dest must have sufficient space,
+ * len+ZLIB_COMPRESS_EXPANSION */
 static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
 
 	unsigned int endpos = src->pos + len;
@@ -648,38 +649,28 @@
 
 	TRACE2(("enter buf_compress"))
 
-	while (1) {
-
-		ses.keys->trans.zstream->avail_in = endpos - src->pos;
-		ses.keys->trans.zstream->next_in = 
-			buf_getptr(src, ses.keys->trans.zstream->avail_in);
+	dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
 
-		ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
-		ses.keys->trans.zstream->next_out =
-			buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
+	ses.keys->trans.zstream->avail_in = endpos - src->pos;
+	ses.keys->trans.zstream->next_in = 
+		buf_getptr(src, ses.keys->trans.zstream->avail_in);
 
-		result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
-
-		buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
-		buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
-		buf_setpos(dest, dest->len);
+	ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
+	ses.keys->trans.zstream->next_out =
+		buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
 
-		if (result != Z_OK) {
-			dropbear_exit("zlib error");
-		}
+	result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
 
-		if (ses.keys->trans.zstream->avail_in == 0) {
-			break;
-		}
+	buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
+	buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
+	buf_setpos(dest, dest->len);
 
-		dropbear_assert(ses.keys->trans.zstream->avail_out == 0);
+	if (result != Z_OK) {
+		dropbear_exit("zlib error");
+	}
 
-		/* the buffer has been filled, we must extend. This only happens in
-		 * unusual circumstances where the data grows in size after deflate(),
-		 * but it is possible */
-		buf_resize(dest, dest->size + ZLIB_COMPRESS_EXPANSION);
-
-	}
+	/* fails if destination buffer wasn't large enough */
+	dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
 	TRACE2(("leave buf_compress"))
 }
 #endif