Commit 9b36b7d9 authored by Matt Caswell's avatar Matt Caswell
Browse files

Add support for initialising WPACKETs from a static buffer



Normally WPACKETs will use a BUF_MEM which can grow as required. Sometimes
though that may be overkill for what is needed - a static buffer may be
sufficient. This adds that capability.

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent 327c1627
Loading
Loading
Loading
Loading
+41 −14
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
    return 1;
}

#define GETBUF(p)   (((p)->staticbuf != NULL) \
                     ? (p)->staticbuf : (unsigned char *)(p)->buf->data)

int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
{
    /* Internal API, so should not fail */
@@ -43,7 +46,7 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
    if (pkt->maxsize - pkt->written < len)
        return 0;

    if (pkt->buf->length - pkt->written < len) {
    if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) {
        size_t newlen;
        size_t reflen;

@@ -59,7 +62,7 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
        if (BUF_MEM_grow(pkt->buf, newlen) == 0)
            return 0;
    }
    *allocbytes = (unsigned char *)pkt->buf->data + pkt->curr;
    *allocbytes = GETBUF(pkt) + pkt->curr;

    return 1;
}
@@ -83,19 +86,12 @@ static size_t maxmaxsize(size_t lenbytes)
    return ((size_t)1 << (lenbytes * 8)) - 1 + lenbytes;
}

int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
{
    unsigned char *lenchars;

    /* Internal API, so should not fail */
    assert(buf != NULL);
    if (buf == NULL)
        return 0;

    pkt->buf = buf;
    pkt->curr = 0;
    pkt->written = 0;
    pkt->maxsize = maxmaxsize(lenbytes);

    pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs));
    if (pkt->subs == NULL)
@@ -112,11 +108,42 @@ int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
        pkt->subs = NULL;
        return 0;
    }
    pkt->subs->packet_len = lenchars - (unsigned char *)pkt->buf->data;
    pkt->subs->packet_len = lenchars - GETBUF(pkt);

    return 1;
}

int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
                            size_t lenbytes)
{
    size_t max = maxmaxsize(lenbytes);

    /* Internal API, so should not fail */
    assert(buf != NULL && len > 0);
    if (buf == NULL || len == 0)
        return 0;

    pkt->staticbuf = buf;
    pkt->buf = NULL;
    pkt->maxsize = (max < len) ? max : len;

    return wpacket_intern_init_len(pkt, lenbytes);
}

int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes)
{
    /* Internal API, so should not fail */
    assert(buf != NULL);
    if (buf == NULL)
        return 0;

    pkt->staticbuf = NULL;
    pkt->buf = buf;
    pkt->maxsize = maxmaxsize(lenbytes);

    return wpacket_intern_init_len(pkt, lenbytes);
}

int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
{
    return WPACKET_init_len(pkt, buf, 0);
@@ -179,8 +206,8 @@ static int wpacket_intern_close(WPACKET *pkt)

    /* Write out the WPACKET length if needed */
    if (sub->lenbytes > 0
                && !put_value((unsigned char *)&pkt->buf->data[sub->packet_len],
                              packlen, sub->lenbytes))
                && !put_value(&GETBUF(pkt)[sub->packet_len], packlen,
                              sub->lenbytes))
            return 0;

    pkt->subs = sub->parent;
@@ -248,7 +275,7 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
    if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
        return 0;
    /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
    sub->packet_len = lenchars - (unsigned char *)pkt->buf->data;
    sub->packet_len = lenchars - GETBUF(pkt);

    return 1;
}
+10 −0
Original line number Diff line number Diff line
@@ -625,6 +625,9 @@ struct wpacket_st {
    /* The buffer where we store the output data */
    BUF_MEM *buf;

    /* Fixed sized buffer which can be used as an alternative to buf */
    unsigned char *staticbuf;

    /*
     * Offset into the buffer where we are currently writing. We use an offset
     * in case the buffer grows and gets reallocated.
@@ -670,6 +673,13 @@ int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
 */
int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);

/*
 * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
 * A fixed buffer of memory |buf| of size |len| is used instead. A failure will
 * occur if you attempt to write beyond the end of the buffer
 */
int WPACKET_init_static_len(WPACKET *pkt, unsigned char *buf, size_t len,
                            size_t lenbytes);
/*
 * Set the flags to be applied to the current sub-packet
 */
+27 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ const static unsigned char seqsub[] = { 0x01, 0xff, 0x01, 0xff };
const static unsigned char empty = 0x00;
const static unsigned char alloc[] = { 0x02, 0xfe, 0xff };
const static unsigned char submem[] = { 0x03, 0x02, 0xfe, 0xff };
const static unsigned char fixed[] = { 0xff, 0xff, 0xff };

static BUF_MEM *buf;

@@ -34,6 +35,7 @@ static int test_WPACKET_init(void)
    WPACKET pkt;
    int i;
    size_t written;
    unsigned char sbuf[3];

    if (!WPACKET_init(&pkt, buf)
            || !WPACKET_put_bytes_u8(&pkt, 0xff)
@@ -95,6 +97,31 @@ static int test_WPACKET_init(void)
        return 0;
    }

    /* Test initialising from a fixed size buffer */
    if (!WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 0)
                /* Adding 3 bytes should succeed */
            || !WPACKET_put_bytes_u24(&pkt, 0xffffff)
                /* Adding 1 more byte should fail */
            ||  WPACKET_put_bytes_u8(&pkt, 0xff)
                /* Finishing the top level WPACKET should succeed */
            || !WPACKET_finish(&pkt)
            || !WPACKET_get_total_written(&pkt, &written)
            ||  written != sizeof(fixed)
            || memcmp(sbuf, fixed, sizeof(sbuf)) != 0
                /* Initialise with 1 len byte */
            || !WPACKET_init_static_len(&pkt, sbuf, sizeof(sbuf), 1)
                /* Adding 2 bytes should succeed */
            || !WPACKET_put_bytes_u16(&pkt, 0xfeff)
                /* Adding 1 more byte should fail */
            ||  WPACKET_put_bytes_u8(&pkt, 0xff)
            || !WPACKET_finish(&pkt)
            || !WPACKET_get_total_written(&pkt, &written)
            ||  written != sizeof(alloc)
            ||  memcmp(sbuf, alloc, written) != 0) {
        testfail("test_WPACKET_init():5 failed\n", &pkt);
        return 0;
    }

    return 1;
}