From 1a3ebc620d1ba01ac44602303388dc454d4378f5 Mon Sep 17 00:00:00 2001 From: Volodymyr Chernetskyi <19735328+chernetskyi@users.noreply.github.com> Date: Thu, 10 Sep 2026 10:49:05 +0200 Subject: [PATCH] fix(klib): parenthesize kvec macro arguments Problem: The kvec append and reserve macros do not parenthesize length arguments. Compound expressions can change the allocation and copy sizes, causing buffer overflows for elements larger than one byte. The append macros also expand to bare if statements, making them unsafe to use in unbraced if/else statements. Solution: Parenthesize length and data arguments and wrap both append macros in do/while statements. AI-assisted --- src/klib/kvec.h | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/klib/kvec.h b/src/klib/kvec.h index cc0fc3dcbd..440ed55931 100644 --- a/src/klib/kvec.h +++ b/src/klib/kvec.h @@ -97,22 +97,24 @@ /// fit at least "len" more items #define kv_ensure_space(v, len) \ do { \ - if ((v).capacity < (v).size + len) { \ - (v).capacity = (v).size + len; \ + if ((v).capacity < (v).size + (len)) { \ + (v).capacity = (v).size + (len); \ kv_roundup32((v).capacity); \ kv_resize((v), (v).capacity); \ } \ } while (0) #define kv_concat_len(v, data, len) \ - if (len > 0) { \ - kv_ensure_space(v, len); \ - assert((v).items); \ - /* kv_roundup32() only ORs bits in, so kv_ensure_space() leaves capacity >= size+len. */ \ - /* coverity[overrun-buffer-arg] */ \ - memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \ - (v).size = (v).size + len; \ - } + do { \ + if ((len) > 0) { \ + kv_ensure_space(v, len); \ + assert((v).items); \ + /* kv_roundup32() only ORs bits in, so kv_ensure_space() leaves capacity >= size+len. */ \ + /* coverity[overrun-buffer-arg] */ \ + memcpy((v).items + (v).size, (data), sizeof((v).items[0]) * (len)); \ + (v).size = (v).size + (len); \ + } \ + } while (0) /// Appends a string to `v`, without its NUL. #define kv_concat(v, str) kv_concat_len(v, str, strlen(str)) @@ -223,20 +225,22 @@ static inline void *_memcpy_free(void *const restrict dest, void *const restrict /// fit at least "len" more items #define kvi_ensure_more_space(v, len) \ do { \ - if ((v).capacity < (v).size + len) { \ - (v).capacity = (v).size + len; \ + if ((v).capacity < (v).size + (len)) { \ + (v).capacity = (v).size + (len); \ kv_roundup32((v).capacity); \ kvi_resize((v), (v).capacity); \ } \ } while (0) #define kvi_concat_len(v, data, len) \ - if (len > 0) { \ - kvi_ensure_more_space(v, len); \ - assert((v).items); \ - memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \ - (v).size = (v).size + len; \ - } + do { \ + if ((len) > 0) { \ + kvi_ensure_more_space(v, len); \ + assert((v).items); \ + memcpy((v).items + (v).size, (data), sizeof((v).items[0]) * (len)); \ + (v).size = (v).size + (len); \ + } \ + } while (0) #define kvi_concat(v, str) kvi_concat_len(v, str, strlen(str)) #define kvi_splice(v1, v0) kvi_concat_len(v1, (v0).items, (v0).size)