Also added the WPACKET_cleanup() function to cleanup a WPACKET if we hit
an error.
Reviewed-by: Rich Salz <rsalz@openssl.org>
+#define DEFAULT_BUF_SIZE 256
+
/*
* Allocate bytes in the WPACKET for the output. This reserves the bytes
* and count them as "written", but doesn't actually do the writing.
/*
* Allocate bytes in the WPACKET for the output. This reserves the bytes
* and count them as "written", but doesn't actually do the writing.
if (SIZE_MAX - pkt->written < len)
return 0;
if (SIZE_MAX - pkt->written < len)
return 0;
- if (pkt->maxsize > 0 && pkt->written + len > pkt->maxsize)
+ if (pkt->written + len > pkt->maxsize)
return 0;
if (pkt->buf->length - pkt->written < len) {
size_t newlen;
return 0;
if (pkt->buf->length - pkt->written < len) {
size_t newlen;
- if (pkt->buf->length > SIZE_MAX / 2)
+ if (pkt->buf->length > SIZE_MAX / 2) {
- else
- newlen = pkt->buf->length * 2;
+ } else {
+ if (pkt->buf->length == 0)
+ newlen = DEFAULT_BUF_SIZE;
+ else
+ newlen = pkt->buf->length * 2;
+ }
if (BUF_MEM_grow(pkt->buf, newlen) == 0)
return 0;
if (BUF_MEM_grow(pkt->buf, newlen) == 0)
return 0;
+ if (pkt->curr == NULL) {
+ /*
+ * Can happen if initialised with a BUF_MEM that hasn't been
+ * pre-allocated.
+ */
+ pkt->curr = (unsigned char *)pkt->buf->data;
+ }
}
pkt->written += len;
*allocbytes = pkt->curr;
}
pkt->written += len;
*allocbytes = pkt->curr;
+static size_t maxmaxsize(size_t lenbytes)
+{
+ if (lenbytes >= sizeof(size_t) || lenbytes == 0)
+ return SIZE_MAX;
+ else
+ return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
+}
+
/*
* Initialise a WPACKET with the buffer in |buf|. The buffer must exist
* for the whole time that the WPACKET is being used. Additionally |lenbytes| of
/*
* Initialise a WPACKET with the buffer in |buf|. The buffer must exist
* for the whole time that the WPACKET is being used. Additionally |lenbytes| of
pkt->buf = buf;
pkt->curr = (unsigned char *)buf->data;
pkt->written = 0;
pkt->buf = buf;
pkt->curr = (unsigned char *)buf->data;
pkt->written = 0;
+ pkt->maxsize = maxmaxsize(lenbytes);
pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
if (pkt->subs == NULL)
pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
if (pkt->subs == NULL)
int WPACKET_set_packet_len(WPACKET *pkt, unsigned char *packet_len,
size_t lenbytes)
{
int WPACKET_set_packet_len(WPACKET *pkt, unsigned char *packet_len,
size_t lenbytes)
{
/* We only allow this to be set once */
/* We only allow this to be set once */
+ if (pkt->subs == NULL || pkt->subs->lenbytes != 0)
return 0;
pkt->subs->lenbytes = lenbytes;
pkt->subs->packet_len = packet_len;
return 0;
pkt->subs->lenbytes = lenbytes;
pkt->subs->packet_len = packet_len;
+ maxmax = maxmaxsize(lenbytes);
+ if (pkt->maxsize > maxmax)
+ pkt->maxsize = maxmax;
+
ret = wpacket_intern_close(pkt);
ret = wpacket_intern_close(pkt);
- /* We free up memory no matter whether |ret| is zero or not */
- OPENSSL_free(pkt->subs);
- pkt->subs = NULL;
+ if (ret) {
+ OPENSSL_free(pkt->subs);
+ pkt->subs = NULL;
+ }
-/*
- * Set a maximum size that we will not allow the WPACKET to grow beyond. If not
- * set then there is no maximum.
- */
+/* Set a maximum size that we will not allow the WPACKET to grow beyond */
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
{
int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize)
{
+ WPACKET_SUB *sub;
+ size_t lenbytes;
+
+ if (pkt->subs == NULL)
+ return 0;
+
+ /* Find the WPACKET_SUB for the top level */
+ for (sub = pkt->subs; sub->parent != NULL; sub = sub->parent);
+
+ lenbytes = sub->lenbytes;
+ if (lenbytes == 0)
+ lenbytes = sizeof(pkt->maxsize);
+
+ if (maxmaxsize(lenbytes) < maxsize || maxsize < pkt->written)
+ return 0;
+
pkt->maxsize = maxsize;
return 1;
pkt->maxsize = maxsize;
return 1;
- * Return the total number of bytes written so far to the underlying buffer.
- * This might includes bytes written by a parent WPACKET.
+ * Return the total number of bytes written so far to the underlying buffer
+ * including any storage allocated for length bytes
*/
int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
{
*/
int WPACKET_get_total_written(WPACKET *pkt, size_t *written)
{
- if (pkt->subs == NULL || written == NULL)
return 0;
*written = pkt->written;
return 0;
*written = pkt->written;
+
+/*
+ * Release resources in a WPACKET if a failure has occurred.
+ */
+void WPACKET_cleanup(WPACKET *pkt)
+{
+ WPACKET_SUB *sub, *parent;
+
+ for (sub = pkt->subs; sub != NULL; sub = parent) {
+ parent = sub->parent;
+ OPENSSL_free(sub);
+ }
+ pkt->subs = NULL;
+}
- * Maximum number of bytes we will allow to be written to this WPACKET. Zero
- * if no maximum
+ * Maximum number of bytes we will allow to be written to this WPACKET.
size_t lenbytes);
int WPACKET_get_total_written(WPACKET *pkt, size_t *written);
int WPACKET_get_length(WPACKET *pkt, size_t *len);
size_t lenbytes);
int WPACKET_get_total_written(WPACKET *pkt, size_t *written);
int WPACKET_get_length(WPACKET *pkt, size_t *len);
+void WPACKET_cleanup(WPACKET *pkt);