commit 1427b94200d62ccf52f47534b1adcdb25ccbae00
parent ad1c07ebb98679712eb1702a69902710a23f9f47
Author: bfredl <bjorn.linse@gmail.com>
Date: Thu, 1 Jan 2026 10:55:14 +0100
fix(typval): allocated dynamic size must be at least the static size
fixes #37160
Diffstat:
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
@@ -2029,7 +2029,9 @@ dictitem_T *tv_dict_item_alloc_len(const char *const key, const size_t key_len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
FUNC_ATTR_MALLOC
{
- dictitem_T *const di = xmalloc(offsetof(dictitem_T, di_key) + key_len + 1);
+ // Allocating a struct smaller than its static size is UB (#37160)
+ dictitem_T *const di = xmalloc(MAX(sizeof(dictitem_T),
+ offsetof(dictitem_T, di_key) + key_len + 1));
memcpy(di->di_key, key, key_len);
di->di_key[key_len] = NUL;
di->di_flags = DI_FLAGS_ALLOC;
diff --git a/test/unit/eval/testutil.lua b/test/unit/eval/testutil.lua
@@ -413,7 +413,7 @@ local function alloc_len(len, get_ptr)
if type(len) == 'string' or type(len) == 'table' then
return #len
elseif len == nil then
- return eval.strlen(get_ptr())
+ return tonumber(eval.strlen(get_ptr()))
else
return len
end
@@ -435,7 +435,7 @@ local alloc_logging_t = {
end)
return {
func = 'malloc',
- args = { ffi.offsetof('dictitem_T', 'di_key') + size + 1 },
+ args = { math.max(ffi.sizeof('dictitem_T'), ffi.offsetof('dictitem_T', 'di_key') + size + 1) },
ret = void(di),
}
end,