summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2015-03-01 21:16:09 +0800
committerMatt Johnston <matt@ucc.asn.au>2015-03-01 21:16:09 +0800
commita7f360f887d0c7aef387e324f3c4e8f4c94a3d78 (patch)
tree52889fbe90493748f0417f395595617566e80e9b
parent0147fa3408e07926165142b1c479dbe3b11efccf (diff)
downloaddropbear-a7f360f887d0c7aef387e324f3c4e8f4c94a3d78.tar.gz
allocate buffer and data in a single allocation
-rw-r--r--buffer.c32
-rw-r--r--buffer.h6
-rw-r--r--cli-agentfwd.c2
-rw-r--r--packet.c49
4 files changed, 40 insertions, 49 deletions
diff --git a/buffer.c b/buffer.c
index 2b35f72..d043bdb 100644
--- a/buffer.c
+++ b/buffer.c
@@ -46,17 +46,15 @@ buffer* buf_new(unsigned int size) {
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 @@ buffer* buf_new(unsigned int size) {
/* 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 @@ void buf_burn(buffer* buf) {
/* 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 @@ unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) {
/* 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;
}
diff --git a/buffer.h b/buffer.h
index 5f59939..6ab53d7 100644
--- a/buffer.h
+++ b/buffer.h
@@ -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 @@ struct buf {
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);
diff --git a/cli-agentfwd.c b/cli-agentfwd.c
index aea5e64..c9bc9db 100644
--- a/cli-agentfwd.c
+++ b/cli-agentfwd.c
@@ -155,7 +155,7 @@ static buffer * agent_request(unsigned char type, buffer *data) {
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) {
diff --git a/packet.c b/packet.c
index d38d8f4..42bcc99 100644
--- a/packet.c
+++ b/packet.c
@@ -257,7 +257,7 @@ static int read_packet_init() {
}
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 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) {
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 @@ static void make_mac(unsigned int seqno, const struct key_context_directional *
#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 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
TRACE2(("enter buf_compress"))
- while (1) {
+ dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
- ses.keys->trans.zstream->avail_in = endpos - src->pos;
- ses.keys->trans.zstream->next_in =
- buf_getptr(src, ses.keys->trans.zstream->avail_in);
+ ses.keys->trans.zstream->avail_in = endpos - src->pos;
+ ses.keys->trans.zstream->next_in =
+ buf_getptr(src, ses.keys->trans.zstream->avail_in);
- 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_out = dest->size - dest->pos;
+ ses.keys->trans.zstream->next_out =
+ buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
- result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
+ 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);
-
- if (result != Z_OK) {
- dropbear_exit("zlib error");
- }
-
- if (ses.keys->trans.zstream->avail_in == 0) {
- break;
- }
-
- dropbear_assert(ses.keys->trans.zstream->avail_out == 0);
-
- /* 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);
+ 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);
+ if (result != Z_OK) {
+ dropbear_exit("zlib error");
}
+
+ /* fails if destination buffer wasn't large enough */
+ dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
TRACE2(("leave buf_compress"))
}
#endif