i_free(field->name);
field->name = i_strdup(name);
+ size_t old_size = MALLOC_MULTIPLY(
+ sizeof(limit->alt_username_hashes[0]), old_count);
+ size_t new_size = MALLOC_MULTIPLY(
+ sizeof(limit->alt_username_hashes[0]),
+ I_MAX((idx+1), old_count));
limit->alt_username_hashes =
i_realloc(limit->alt_username_hashes,
- sizeof(limit->alt_username_hashes[0]) *
- old_count,
- sizeof(limit->alt_username_hashes[0]) *
- I_MAX((idx+1), old_count));
+ old_size, new_size);
if (!hash_table_is_created(limit->alt_username_hashes[idx])) {
hash_table_create(&limit->alt_username_hashes[idx],
default_pool, 0, str_hash, strcmp);
patterns_count = i;
/* now we know how much memory we need */
- glob = p_malloc(pool, sizeof(struct imap_match_glob) +
- patterns_data_len);
+ size_t glob_alloc_size =
+ MALLOC_ADD(sizeof(struct imap_match_glob), patterns_data_len);
+ glob = p_malloc(pool, glob_alloc_size);
glob->pool = pool;
glob->sep = separator;
}
size_t prefix_len = strlen(prefix);
size_t value_path_len = strlen(value_path);
- char *buf = p_malloc(pool, prefix_len + value_path_len + 1 +
- st.st_size + 1);
+ size_t buf_size = MALLOC_ADD3(prefix_len, value_path_len, 1);
+ buf_size = MALLOC_ADD3(buf_size, (size_t)st.st_size, 1);
+ char *buf = p_malloc(pool, buf_size);
memcpy(buf, prefix, prefix_len);
memcpy(buf + prefix_len, value_path, value_path_len);
buf[prefix_len + value_path_len] = '\n';
const char *path = file->path != NULL ? file->path : "";
size_t path_len = strlen(path);
size_t content_len = strlen(file->content);
+ size_t value_size = MALLOC_ADD3(path_len, 1, content_len);
+ value_size = MALLOC_ADD(value_size, 1);
- char *value = p_malloc(pool, path_len + 1 + content_len + 1);
+ char *value = p_malloc(pool, value_size);
memcpy(value, path, path_len);
value[path_len] = '\n';
memcpy(value + path_len + 1, file->content, content_len);
return 0;
/* @UNSAFE */
- new_str = p_malloc(pool, i + strlen(str+i) + 1);
+ new_str = p_malloc(pool, MALLOC_ADD3(i, strlen(str+i), 1));
memcpy(new_str, str, i);
for (j = i; str[i] != '\0'; i++) {
if (str[i] == '\n') {
/* nearest_power() returns 2^n values, so alloc_size can't be
anywhere close to SIZE_MAX */
- block = malloc(SIZEOF_MEMBLOCK + alloc_size);
+ block = malloc(MALLOC_ADD(SIZEOF_MEMBLOCK, alloc_size));
if (unlikely(block == NULL)) {
if (outofmem) {
if (min_size > outofmem_area.block.left)
value->next = NULL;
memset(value + 1, 0, hash->value_size);
} else {
- value = p_malloc(hash->value_pool,
- sizeof(*value) + hash->value_size);
+ size_t value_alloc_size =
+ MALLOC_ADD(sizeof(*value), hash->value_size);
+ value = p_malloc(hash->value_pool, value_alloc_size);
}
value->key_hash = key_hash;
malloc_add_check(a, b, sizeof(a), sizeof(size_t), __FILE__, __LINE__) // NOLINT(bugprone-sizeof-expression)
#endif
+/* Minimal convenience wrapper for common allocation size arithmetic.
+ Built on MALLOC_ADD() to keep overflow handling centralized. */
+#define MALLOC_ADD3(a, b, c) \
+ MALLOC_ADD(MALLOC_ADD((a), (b)), (c))
+
#endif
{
i_assert(sample_count > 0);
- struct stats_dist *stats =
- i_malloc(sizeof(struct stats_dist) +
- sizeof(uint64_t) * sample_count);
+ size_t samples_size = MALLOC_MULTIPLY(sizeof(uint64_t), sample_count);
+ size_t alloc_size = MALLOC_ADD(sizeof(struct stats_dist), samples_size);
+ struct stats_dist *stats = i_malloc(alloc_size);
stats->sample_count = sample_count;
return stats;
}
return p_new(pool, char *, 1);
alloc_count = 32;
+ size_t array_size = MALLOC_MULTIPLY(sizeof(char *), alloc_count);
array = pool == unsafe_data_stack_pool ?
- t_malloc_no0(sizeof(char *) * alloc_count) :
- p_malloc(pool, sizeof(char *) * alloc_count);
+ t_malloc_no0(array_size) :
+ p_malloc(pool, array_size);
array[0] = data; count = 1;
char *need_unescape = NULL;
}
if (count+1 >= alloc_count) {
new_alloc_count = nearest_power(alloc_count+1);
+ size_t old_size =
+ MALLOC_MULTIPLY(sizeof(char *), alloc_count);
+ size_t new_size =
+ MALLOC_MULTIPLY(sizeof(char *), new_alloc_count);
array = p_realloc(pool, array,
- sizeof(char *) * alloc_count,
- sizeof(char *) *
- new_alloc_count);
+ old_size, new_size);
alloc_count = new_alloc_count;
}
*data++ = '\0';
/* separator found */
if (count+1 >= alloc_count) {
new_alloc_count = nearest_power(alloc_count+1);
+ size_t old_size =
+ MALLOC_MULTIPLY(sizeof(char *), alloc_count);
+ size_t new_size =
+ MALLOC_MULTIPLY(sizeof(char *), new_alloc_count);
array = p_realloc(pool, array,
- sizeof(char *) * alloc_count,
- sizeof(char *) *
- new_alloc_count);
+ old_size, new_size);
alloc_count = new_alloc_count;
}
/* separator found */
if (count+1 >= alloc_count) {
new_alloc_count = nearest_power(alloc_count+1);
+ size_t old_size =
+ MALLOC_MULTIPLY(sizeof(char *), alloc_count);
+ size_t new_size =
+ MALLOC_MULTIPLY(sizeof(char *), new_alloc_count);
array = p_realloc(pool, array,
- sizeof(char *) * alloc_count,
- sizeof(char *) *
- new_alloc_count);
+ old_size, new_size);
alloc_count = new_alloc_count;
}
*str++ = '\0';
/* regular alloc */
struct test_struct *s1 = i_new(struct test_struct, 2);
- struct test_struct *s2 = i_malloc(sizeof(struct test_struct) * 2);
+ struct test_struct *s2 = i_malloc(
+ MALLOC_MULTIPLY(sizeof(struct test_struct), 2));
s1[0] = ab; s2[0] = ab;
s1[1] = bc; s2[1] = bc;
test_assert(memcmp(s1, s2, sizeof(struct test_struct) * 2) == 0);
/* realloc */
s1 = i_realloc_type(s1, struct test_struct, 2, 4);
- s2 = i_realloc(s2, sizeof(struct test_struct) * 2,
- sizeof(struct test_struct) * 4);
+ s2 = i_realloc(s2,
+ MALLOC_MULTIPLY(sizeof(struct test_struct), 2),
+ MALLOC_MULTIPLY(sizeof(struct test_struct), 4));
s1[2] = cd; s2[2] = cd;
s1[3] = de; s2[3] = de;
test_assert(memcmp(&s1[0], &ab, sizeof(ab)) == 0);
/* allocating new memory with realloc */
s1 = i_realloc_type(NULL, struct test_struct, 0, 2);
- s2 = i_realloc(NULL, 0, sizeof(struct test_struct) * 2);
+ s2 = i_realloc(NULL, 0,
+ MALLOC_MULTIPLY(sizeof(struct test_struct), 2));
s1[0] = ab; s2[0] = ab;
s1[1] = bc; s2[1] = bc;
test_assert(memcmp(s1, s2, sizeof(struct test_struct) * 2) == 0);