From 73dcd7837023939063ad89681c8d4e7392a310fe Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 14 Mar 2022 14:40:18 +0100 Subject: lib: fix potential integer underflow on empty render output The current `uc_render()` implementation uses a `fseek()` call on the `open_memstream()` provided `FILE *` stream to reserve headroom for the `uc_string_t` header. The `fseek()` call alone does not guarantee that the underlying buffer length is updated on all libc implementations though. This may lead to an integer underflow later on when the `uc_string_t` header length is substracted from the buffer length after invoking a template that did not produce any output write operations. In such a case, a very large value is assigned to `ustr->length` leading to uninitialized or out-of-bounds memory accesses later on. Solve this issue by writing the header structure as data using `fwrite()` which should yield the expected behaviour on all libc environments. Signed-off-by: Jo-Philipp Wich --- lib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib.c') diff --git a/lib.c b/lib.c index dc48d84..f715484 100644 --- a/lib.c +++ b/lib.c @@ -2194,6 +2194,7 @@ uc_include(uc_vm_t *vm, size_t nargs) static uc_value_t * uc_render(uc_vm_t *vm, size_t nargs) { + uc_string_t hdr = { .header = { .type = UC_STRING, .refcount = 1 } }; uc_string_t *ustr = NULL; FILE *mem, *prev; size_t len = 0; @@ -2204,7 +2205,7 @@ uc_render(uc_vm_t *vm, size_t nargs) goto out; /* reserve space for uc_string_t header... */ - if (fseek(mem, sizeof(*ustr), SEEK_SET)) + if (fwrite(&hdr, 1, sizeof(hdr), mem) != sizeof(hdr)) goto out; /* divert VM output to memory fd */ @@ -2219,8 +2220,6 @@ uc_render(uc_vm_t *vm, size_t nargs) fclose(mem); /* update uc_string_t length */ - ustr->header.type = UC_STRING; - ustr->header.refcount = 1; ustr->length = len - sizeof(*ustr); return &ustr->header; -- cgit v1.2.3