diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-06-04 20:55:53 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-06-04 20:55:53 +0200 |
commit | 44b0a3b3938333a4f2b00d159fab258a9acd31c1 (patch) | |
tree | a466ad089f3ff0bcbd143d5767c7b222881b4dd6 | |
parent | b211ca0e420d8086d3fa0358413a6f8b44df1115 (diff) |
struct: fix packing `*` format after other repeated formats
When packing a format such as `!6C*`, the `*` format was not included into
the result buffer due to improper tracking of the function argument offset.
Solve this issue by taking field repetitions into account when tracking
the argument offset while calculating the size of dynamic arguments.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | lib/struct.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/lib/struct.c b/lib/struct.c index 5d301db..bd418b2 100644 --- a/lib/struct.c +++ b/lib/struct.c @@ -2182,17 +2182,17 @@ overflow: static uc_value_t * uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) { + size_t ncode, arg, off; formatcode_t *code; - size_t ncode, off; uc_string_t *buf; ssize_t size, n; const void *p; - for (ncode = 0, code = &state->codes[0], off = 0; + for (ncode = 0, code = &state->codes[0], arg = argoff, off = 0; ncode < state->ncodes; code = &state->codes[++ncode]) { if (code->fmtdef->format == '*') { - uc_value_t *v = uc_fn_arg(argoff + ncode); + uc_value_t *v = uc_fn_arg(arg++); if (ucv_type(v) != UC_STRING) continue; @@ -2204,6 +2204,9 @@ uc_pack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) else off += code->size; } + else { + arg += code->repeat; + } } buf = xalloc(sizeof(*buf) + state->size + off + 1); |