Re: svn commit: r1917047 - in /apr/apr/trunk: CHANGES buffer/ buffer/apr_buffer.c build.conf include/apr_buffer.h test/Makefile.in test/Makefile.win test/NWGNUaprtest test/abts_tests.h test/testbuffer.c test/testutil.h

Yann Ylavic <[email protected]>
Newsgroups gmane.comp.apache.apr.devel
Message-ID <CAKQ1sVMx7gzNwP83XYr28cayXVyOFRS0JdQQjbmAy4dKBhC4Hg@mail.gmail.com>
On Tue, Apr 16, 2024 at 10:54 PM <[email protected]> wrote:
>
> --- apr/apr/trunk/buffer/apr_buffer.c (added)
> +++ apr/apr/trunk/buffer/apr_buffer.c Tue Apr 16 20:54:51 2024
> @@ -0,0 +1,408 @@
> +
> +APR_DECLARE(apr_buffer_t *) apr_buffer_mem_make(apr_pool_t *pool,
> +                                                void *mem, apr_size_t len)

Two different possibilities for returning NULL, maybe an
apr_buffer_mem_create() instead returning APR_EINVAL/ENOMEM
accordingly.

> +{
> +    apr_buffer_t *buf;
> +
> +    if (len > APR_INT64_MAX) {
> +        return NULL;
> +    }
> +
> +    buf = apr_palloc(pool, sizeof(apr_buffer_t));
> +
> +    if (buf) {
> +        buf->d.mem = mem;
> +        buf->size = len;
> +    }
> +
> +    return buf;
> +}
> +
> +APR_DECLARE(apr_status_t) apr_buffer_str_set(apr_buffer_t *buf,
> +                                             char *str, apr_ssize_t len)
> +{
> +
> +    if (len > APR_INT64_MAX) {
> +        return APR_EINVAL;
> +    }
> +
> +    if (!str) {
> +        buf->d.str = NULL;
> +        buf->size = 0;
> +    }
> +    else if (len < 0) {
> +        apr_size_t slen = strlen(str);
> +        if (slen <= APR_INT64_MAX) {
> +            buf->d.str = str;
> +            buf->size = -(slen + 1);
> +        }
> +        else {

return APR_EINVAL?

> +            buf->d.str = NULL;
> +            buf->size = 0;
> +        }
> +    }
> +    else {
> +        buf->d.str = str;
> +        buf->size = -(len + 1);
> +    }
> +
> +    return APR_SUCCESS;
> +}
> +
> +APR_DECLARE(apr_buffer_t *) apr_buffer_str_make(apr_pool_t *pool,
> +                                                char *str, apr_ssize_t len)

Likewise several possibilities for returning NULL, apr_buffer_str_create()?

> +{
> +    apr_buffer_t *buf;
> +    apr_int64_t size;
> +    apr_size_t slen;
> +
> +    if (!str) {
> +        str = NULL;
> +        size = 0;
> +    }
> +    if (APR_BUFFER_STRING == len && !str[0]) {
> +        size = len;
> +    }
> +    else if (len < 0) {
> +        slen = strlen(str);
> +        if (slen <= APR_INT64_MAX) {
> +            size = -(slen + 1);
> +        }
> +        else {
> +            return NULL;
> +        }
> +    }
> +    else {
> +        size = -(len + 1);
> +    }
> +
> +    buf = apr_palloc(pool, sizeof(apr_buffer_t));
> +
> +    if (buf) {
> +        buf->d.str = str;
> +        buf->size = size;
> +    }
> +
> +    return buf;
> +}
> +
> +APR_DECLARE(apr_buffer_t *) apr_buffer_null_make(apr_pool_t *pool)
> +{
> +    return apr_pcalloc(pool, sizeof(apr_buffer_t));
> +}
> +
> +APR_DECLARE(apr_size_t) apr_buffer_len(const apr_buffer_t *buf)
> +{
> +    if (buf->size < 0) {
> +        return (apr_size_t)((-buf->size) - 1);
> +    }
> +    else {
> +        return (apr_size_t)buf->size;
> +    }
> +}
> +
> +APR_DECLARE(apr_size_t) apr_buffer_allocated(const apr_buffer_t *buf)

Same as apr_buffer_len()?

> +{
> +    if (buf->size < 0) {
> +        return (apr_size_t)((-buf->size));
> +    }
> +    else {
> +        return (apr_size_t)buf->size;
> +    }
> +}

> +
> +APR_DECLARE(void *) apr_buffer_pmemdup(apr_pool_t *pool, const apr_buffer_t *buf, apr_size_t *size)
> +{
> +    apr_size_t len = apr_buffer_len(buf);
> +
> +    if (size) {
> +        size[0] = len;
> +    }
> +
> +    return apr_pmemdup(pool, buf->d.mem, len);

Should pmemdup() include the '\0' for a "string" buffer?

> +}

> +
> +APR_DECLARE(apr_buffer_t *) apr_buffer_arraydup(const apr_buffer_t *src,
> +                                                apr_buffer_alloc alloc, void *ctx,
> +                                                int nelts)

apr_size_t or at least unsigned int for nelts?

> +{
> +    apr_buffer_t *dst = alloc(ctx, nelts * sizeof(apr_buffer_t));

Maybe check for nelts < APR_SIZE_MAX / sizeof(apr_buffer_t) before
allocating, and fail with APR_EINVAL otherwise?

Also, like apr_buffer_cpy() below, we could allow for allow == NULL
here (and if so maybe move the nelts argument before the alloc and
ctx).

> +    apr_buffer_t *d = dst;
> +
> +    int i;
> +    for (i = 0; i < nelts; i++) {
> +
> +        /* absolute value is size of mem buffer including optional terminating zero */
> +        apr_int64_t size = src->size < 0 ? -src->size : src->size;
> +
> +        void *mem = alloc(ctx, size);
> +        memcpy(mem, src->d.mem, size);
> +
> +        dst->size = src->size;
> +        dst->d.mem = mem;
> +
> +        src++;
> +        dst++;
> +    }
> +
> +    return d;
> +}


> +
> +APR_DECLARE(int) apr_buffer_cmp(const apr_buffer_t *src,
> +                                const apr_buffer_t *dst)
> +{
> +    apr_size_t slen = apr_buffer_len(src);
> +    apr_size_t dlen = apr_buffer_len(dst);
> +
> +    if (slen != dlen) {
> +        return slen < dlen ? -1 : 1;
> +    }
> +    else if (src->d.mem == dst->d.mem) {
> +        /* identical data or both NULL */
> +        return 0;
> +    }
> +    else if (!src->d.mem) {
> +        return -1;
> +    }
> +    else if (!dst->d.mem) {
> +        return 1;
> +    }
> +    else {
> +        return memcmp(src->d.mem, dst->d.mem, slen);
> +    }
> +}
> +
> +
> +APR_DECLARE(int) apr_buffer_ncmp(const apr_buffer_t *src,
> +                                 const apr_buffer_t *dst)

The "n" stands for null here no? I don't have a better name but it
sounds like it'd compare n buffers.
Is it really useful in the first place though, why would anyone want
to pass NULLs here? Only defensive programming?

> +{
> +    if (!src || !src->d.mem) {
> +        if (!dst || !dst->d.mem) {
> +            return 0;
> +        }
> +        else {
> +            return -1;
> +        }
> +    }
> +    else {
> +        if (!dst || !dst->d.mem) {
> +            return 1;
> +        }
> +        else {
> +            return apr_buffer_cmp(src, dst);
> +        }
> +    }

So it's the same as:

    if (!src) {
        return dst ? 1 : 0;
    }
    if (!dst) {
        return -1;
    }
    return apr_buffer_cmp(src, dst);
?

> +}

> +
> +APR_DECLARE(char *) apr_buffer_pstrncat(apr_pool_t *p, const apr_buffer_t *buf,
> +                                        int nelts, const char *sep, int flags,
> +                                        apr_size_t *nbytes)

Likewise, please use an unsigned type for nelts, it can't be negative after all.

> +{
> +    const apr_buffer_t *src = buf;
> +    apr_size_t seplen = sep ? strlen(sep) : 0;
> +    apr_size_t size = 0;
> +
> +    char *dst, *str;
> +
> +    int i;
> +    for (i = 0; i < nelts; i++) {
> +
> +        if (i > 0) {
> +            size += seplen;
> +        }
> +
> +        if (src->size < 0) {
> +            size += (-src->size) - 1;
> +        }
> +        else {
> +            if (APR_BUFFER_NONE == flags) {
> +                size += src->size;
> +            }
> +            else if (APR_BUFFER_BASE64 == flags) {
> +                apr_size_t b64len;
> +
> +                if (APR_SUCCESS != apr_encode_base64(NULL, src->d.mem, src->size,
> +                                                     APR_ENCODE_NONE, &b64len)) {
> +                    return NULL;
> +                }
> +                size += b64len - 1;
> +            }
> +        }
> +
> +        src++;
> +    }
> +
> +    if (nbytes) {
> +        *nbytes = size;
> +    }
> +
> +    str = dst = apr_palloc(p, size + 1);
> +
> +    src = buf;
> +
> +    for (i = 0; i < nelts; i++) {
> +
> +        if (i > 0 && sep) {
> +            strncpy(dst, sep, seplen);

memcpy() should be enough.

> +            dst += seplen;
> +        }
> +
> +        if (src->size < 0) {
> +            strncpy(dst, src->d.str, (-src->size) - 1);

Likewise, memcpy().

> +            dst += (-src->size) - 1;
> +        }
> +        else {
> +            if (APR_BUFFER_NONE == flags) {
> +                memcpy(dst, src->d.mem, src->size);
> +            }
> +            else if (APR_BUFFER_BASE64 == flags) {
> +                apr_size_t b64len;
> +
> +                if (APR_SUCCESS != apr_encode_base64(dst, src->d.mem, src->size,
> +                                                     APR_ENCODE_NONE, &b64len)) {
> +                    return NULL;
> +                }
> +                dst += b64len;
> +            }
> +        }
> +
> +        src++;
> +    }
> +
> +    dst[0] = 0;
> +
> +    return str;
> +}


Regards;
Yann.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.