diff options
| author | Mattias Andrée <m@maandree.se> | 2026-05-06 21:59:06 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-05-06 21:59:06 +0200 |
| commit | b1d1158db0b9634a59dc717a7f0622e1da3df6f4 (patch) | |
| tree | eb6848786524a0aa088e02ae41bacde894bd0f69 /vmemalloc.c | |
| parent | Fix signness issue (diff) | |
| download | libsimple-b1d1158db0b9634a59dc717a7f0622e1da3df6f4.tar.gz libsimple-b1d1158db0b9634a59dc717a7f0622e1da3df6f4.tar.bz2 libsimple-b1d1158db0b9634a59dc717a7f0622e1da3df6f4.tar.xz | |
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'vmemalloc.c')
| -rw-r--r-- | vmemalloc.c | 52 |
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; |
