aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vmemalloc.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/vmemalloc.c b/vmemalloc.c
index 2cac8dd..72e65d2 100644
--- a/vmemalloc.c
+++ b/vmemalloc.c
@@ -18,14 +18,16 @@ struct memalloc_state {
};
static int
-vmemalloc_parse_size_prod(struct memalloc_state *state, size_t n, size_t arg, va_list *ap)
+vmemalloc_parse_size_prod(struct memalloc_state *state, size_t n, size_t arg, va_list ap, size_t *ap_advance_out)
{
+ *ap_advance_out = 0;
if (state->have_size++)
goto inval;
state->elem_size = arg;
if (n) {
while (--n) {
- arg = va_arg(*ap, size_t);
+ arg = va_arg(ap, size_t);
+ ++*ap_advance_out;
if (!state->elem_size)
continue;
if (LIBSIMPLE_UMUL_OVERFLOW_NONZERO(arg, state->elem_size, &state->elem_size, SIZE_MAX)) {
@@ -37,7 +39,8 @@ vmemalloc_parse_size_prod(struct memalloc_state *state, size_t n, size_t arg, va
if (!arg)
goto inval;
for (;;) {
- arg = va_arg(*ap, size_t);
+ arg = va_arg(ap, size_t);
+ ++*ap_advance_out;
if (!arg)
break;
if (LIBSIMPLE_UMUL_OVERFLOW_NONZERO(arg, state->elem_size, &state->elem_size, SIZE_MAX)) {
@@ -53,15 +56,15 @@ inval:
}
static int
-vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list *ap)
+vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list ap)
{
enum libsimple_memalloc_option opt;
long int page_size;
- va_list *subap;
- size_t arg;
+ va_list *subap, ap_copy;
+ size_t arg, ap_advance;
for (;;) {
- opt = va_arg(*ap, enum libsimple_memalloc_option);
+ opt = va_arg(ap, enum libsimple_memalloc_option);
switch (opt) {
case LIBSIMPLE_MEMALLOC_END:
return 0;
@@ -75,7 +78,7 @@ vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list *ap)
case LIBSIMPLE_MEMALLOC_CONDITIONAL_ZERO_INIT:
if (state->zero_init >= 0)
goto inval;
- state->zero_init = (char)va_arg(*ap, int);
+ state->zero_init = (char)va_arg(ap, int);
state->zero_init = !!state->zero_init;
break;
@@ -89,7 +92,7 @@ vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list *ap)
case LIBSIMPLE_MEMALLOC_ALIGNMENT:
if (state->alignment)
goto inval;
- state->alignment = va_arg(*ap, size_t);
+ state->alignment = va_arg(ap, size_t);
if (!state->alignment)
goto inval;
break;
@@ -121,34 +124,38 @@ vmemalloc_parse_args(struct memalloc_state *state, size_t n, va_list *ap)
case LIBSIMPLE_MEMALLOC_ELEMENT_SIZE:
if (state->elem_size)
goto inval;
- state->elem_size = va_arg(*ap, size_t);
+ state->elem_size = va_arg(ap, size_t);
if (!state->elem_size)
goto inval;
break;
case LIBSIMPLE_MEMALLOC_PRODUCT_SIZE:
- arg = va_arg(*ap, size_t);
- if (vmemalloc_parse_size_prod(state, n, arg, ap))
+ arg = va_arg(ap, size_t);
+ va_copy(ap_copy, ap);
+ if (vmemalloc_parse_size_prod(state, n, arg, ap_copy, &ap_advance))
return -1;
+ va_end(ap_copy);
+ while (ap_advance--)
+ (void) va_arg(ap, size_t);
break;
case LIBSIMPLE_MEMALLOC_VA_PRODUCT_SIZE:
- subap = va_arg(*ap, va_list *);
+ subap = va_arg(ap, va_list *);
arg = va_arg(*subap, size_t);
- if (vmemalloc_parse_size_prod(state, n, arg, subap))
+ if (vmemalloc_parse_size_prod(state, n, arg, *subap, &ap_advance))
return -1;
break;
case LIBSIMPLE_MEMALLOC_1_VA_PRODUCT_SIZE:
- arg = va_arg(*ap, size_t);
- subap = va_arg(*ap, va_list *);
- if (vmemalloc_parse_size_prod(state, n, arg, subap))
+ arg = va_arg(ap, size_t);
+ subap = va_arg(ap, va_list *);
+ if (vmemalloc_parse_size_prod(state, n, arg, *subap, &ap_advance))
return -1;
break;
case LIBSIMPLE_MEMALLOC_VA_LIST:
- subap = va_arg(*ap, va_list *);
- if (vmemalloc_parse_args(state, n, subap))
+ subap = va_arg(ap, va_list *);
+ if (vmemalloc_parse_args(state, n, *subap))
return -1;
break;
@@ -198,9 +205,6 @@ libsimple_vmemalloc(size_t n, va_list ap) /* TODO test ([v]{mem,array}alloc) */
void *ptr = NULL;
int saved_errno;
long int tmp;
- va_list ap_copy; /* required because `ap` may be an array (specific single-element array)
- * that has decayed into a pointer, and so &ap would not be a `va_list *`
- * and casting to `void *` could just obfuscate this critical error */
state.alignment = 0;
state.elem_size = 0;
@@ -212,10 +216,8 @@ libsimple_vmemalloc(size_t n, va_list ap) /* TODO test ([v]{mem,array}alloc) */
state.cache_align = 0;
state.cache_split = 0;
- va_copy(ap_copy, ap);
- if (vmemalloc_parse_args(&state, n, &ap_copy))
+ if (vmemalloc_parse_args(&state, n, ap))
return NULL;
- va_end(ap_copy);
state.elem_size = state.elem_size ? state.elem_size : 1;
state.zero_init = state.zero_init >= 0 ? state.zero_init : 0;