summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2016-11-25 23:22:04 +0000
committerDamien Miller <djm@mindrot.org>2016-11-29 16:48:02 +1100
commita9c746088787549bb5b1ae3add7d06a1b6d93d5e (patch)
tree02fcaaa90ae6ccd042e6197898a1d914592dc57b
parentf0ddedee460486fa0e32fefb2950548009e5026e (diff)
upstream commit
split allocation out of sshbuf_reserve() into a separate sshbuf_allocate() function; ok markus@ Upstream-ID: 11b8a2795afeeb1418d508a2c8095b3355577ec2
-rw-r--r--sshbuf.c76
-rw-r--r--sshbuf.h10
2 files changed, 52 insertions, 34 deletions
diff --git a/sshbuf.c b/sshbuf.c
index 91cbd067..cbf7ed4a 100644
--- a/sshbuf.c
+++ b/sshbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf.c,v 1.7 2016/09/12 01:22:38 deraadt Exp $ */
+/* $OpenBSD: sshbuf.c,v 1.8 2016/11/25 23:22:04 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -316,16 +316,13 @@ sshbuf_check_reserve(const struct sshbuf *buf, size_t len)
}
int
-sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
+sshbuf_allocate(struct sshbuf *buf, size_t len)
{
size_t rlen, need;
u_char *dp;
int r;
- if (dpp != NULL)
- *dpp = NULL;
-
- SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
+ SSHBUF_DBG(("allocate buf = %p len = %zu", buf, len));
if ((r = sshbuf_check_reserve(buf, len)) != 0)
return r;
/*
@@ -333,36 +330,49 @@ sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
* then pack the buffer, zeroing buf->off.
*/
sshbuf_maybe_pack(buf, buf->size + len > buf->max_size);
- SSHBUF_TELL("reserve");
- if (len + buf->size > buf->alloc) {
- /*
- * Prefer to alloc in SSHBUF_SIZE_INC units, but
- * allocate less if doing so would overflow max_size.
- */
- need = len + buf->size - buf->alloc;
- rlen = ROUNDUP(buf->alloc + need, SSHBUF_SIZE_INC);
- SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
- if (rlen > buf->max_size)
- rlen = buf->alloc + need;
- SSHBUF_DBG(("adjusted rlen %zu", rlen));
- if ((dp = realloc(buf->d, rlen)) == NULL) {
- SSHBUF_DBG(("realloc fail"));
- if (dpp != NULL)
- *dpp = NULL;
- return SSH_ERR_ALLOC_FAIL;
- }
- buf->alloc = rlen;
- buf->cd = buf->d = dp;
- if ((r = sshbuf_check_reserve(buf, len)) < 0) {
- /* shouldn't fail */
- if (dpp != NULL)
- *dpp = NULL;
- return r;
- }
+ SSHBUF_TELL("allocate");
+ if (len + buf->size <= buf->alloc)
+ return 0; /* already have it. */
+
+ /*
+ * Prefer to alloc in SSHBUF_SIZE_INC units, but
+ * allocate less if doing so would overflow max_size.
+ */
+ need = len + buf->size - buf->alloc;
+ rlen = ROUNDUP(buf->alloc + need, SSHBUF_SIZE_INC);
+ SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
+ if (rlen > buf->max_size)
+ rlen = buf->alloc + need;
+ SSHBUF_DBG(("adjusted rlen %zu", rlen));
+ if ((dp = realloc(buf->d, rlen)) == NULL) {
+ SSHBUF_DBG(("realloc fail"));
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ buf->alloc = rlen;
+ buf->cd = buf->d = dp;
+ if ((r = sshbuf_check_reserve(buf, len)) < 0) {
+ /* shouldn't fail */
+ return r;
}
+ SSHBUF_TELL("done");
+ return 0;
+}
+
+int
+sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
+{
+ u_char *dp;
+ int r;
+
+ if (dpp != NULL)
+ *dpp = NULL;
+
+ SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
+ if ((r = sshbuf_allocate(buf, len)) != 0)
+ return r;
+
dp = buf->d + buf->size;
buf->size += len;
- SSHBUF_TELL("done");
if (dpp != NULL)
*dpp = dp;
return 0;
diff --git a/sshbuf.h b/sshbuf.h
index 52ff017c..1ac4b8c0 100644
--- a/sshbuf.h
+++ b/sshbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf.h,v 1.7 2016/05/02 08:49:03 djm Exp $ */
+/* $OpenBSD: sshbuf.h,v 1.8 2016/11/25 23:22:04 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -139,6 +139,14 @@ u_char *sshbuf_mutable_ptr(const struct sshbuf *buf);
int sshbuf_check_reserve(const struct sshbuf *buf, size_t len);
/*
+ * Preallocates len additional bytes in buf.
+ * Useful for cases where the caller knows how many bytes will ultimately be
+ * required to avoid realloc in the buffer code.
+ * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
+ */
+int sshbuf_allocate(struct sshbuf *buf, size_t len);
+
+/*
* Reserve len bytes in buf.
* Returns 0 on success and a pointer to the first reserved byte via the
* optional dpp parameter or a negative * SSH_ERR_* error code on failure.