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.