diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2026-05-21 17:13:42 -0700 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2026-05-23 19:18:53 -0700 |
| commit | 64eb869b68835e15b46a217a6d955605b78044bc (patch) | |
| tree | 3cb6b850b11fd87ec7167e491218eda030fa2883 /src | |
| parent | c72e6cdc464e295d821da24232a2913bbcecf3f8 (diff) | |
Be more careful about size multiplication
* src/alloc.c (xcalloc): New function.
* src/dispnew.c (save_current_matrix):
* src/fns.c (Finternal__hash_table_histogram):
* src/nsfns.m (Fns_display_monitor_attributes_list):
* src/pgtkfns.c (Fpgtk_display_monitor_attributes_list):
* src/pgtkselect.c (pgtk_own_selection):
* src/profiler.c (make_log):
* src/sfnt.c (sfnt_poly_edges_exact):
* src/xfns.c (x_get_monitor_attributes_xinerama)
(x_get_monitor_attributes_xrandr, Fx_display_monitor_attributes_list):
Use it instead of multiplying by hand, conceivably with overflow.
* src/profiler.c (make_log):
Check for overflow in internal size calculations.
Use xnmalloc instead of multiply + xmalloc.
* src/sfnt.c (xzalloc) [TEST]: Remove, replacing with ...
(xicalloc) [TEST]: ... this new function. All callers changed.
(eassert) [TEST]: New macro.
* src/treesit.c (treesit_calloc_wrapper): Remove, replacing its
use with xcalloc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 20 | ||||
| -rw-r--r-- | src/dispnew.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/nsfns.m | 2 | ||||
| -rw-r--r-- | src/pgtkfns.c | 2 | ||||
| -rw-r--r-- | src/pgtkselect.c | 2 | ||||
| -rw-r--r-- | src/profiler.c | 15 | ||||
| -rw-r--r-- | src/sfnt.c | 14 | ||||
| -rw-r--r-- | src/treesit.c | 8 | ||||
| -rw-r--r-- | src/xfns.c | 8 | ||||
| -rw-r--r-- | src/xterm.c | 4 |
12 files changed, 48 insertions, 33 deletions
diff --git a/src/alloc.c b/src/alloc.c index 387b196bbee..6a81fed2d69 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -656,7 +656,10 @@ xmalloc (size_t size) return val; } -/* Like the above, but zeroes out the memory just allocated. */ +/* Like the above, but zero out the memory just allocated. + Calling this can be faster than allocating and zeroing, + as the calloc implementation can avoid the zeroing overhead + when obtaining memory directly from the operating system. */ void * xzalloc (size_t size) @@ -668,6 +671,21 @@ xzalloc (size_t size) return val; } +/* Like xzalloc, but for an array of N objects each of size S. */ + +void * +xcalloc (size_t n, size_t s) +{ + void *val = calloc (n, s); + if (!val) + { + size_t size; + memory_full (ckd_mul (&size, n, s) ? SIZE_MAX : size); + } + MALLOC_PROBE (n * s); + return val; +} + /* Like realloc but check for no memory and block interrupt input. */ void * diff --git a/src/dispnew.c b/src/dispnew.c index be15a5ab694..7930fa59968 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1963,7 +1963,7 @@ save_current_matrix (struct frame *f) int i; struct glyph_matrix *saved = xzalloc (sizeof *saved); saved->nrows = f->current_matrix->nrows; - saved->rows = xzalloc (saved->nrows * sizeof *saved->rows); + saved->rows = xcalloc (saved->nrows, sizeof *saved->rows); for (i = 0; i < saved->nrows; ++i) { diff --git a/src/fns.c b/src/fns.c index 8e7e5f980a1..98671fc1318 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5996,7 +5996,7 @@ DEFUN ("internal--hash-table-histogram", { struct Lisp_Hash_Table *h = check_hash_table (hash_table); ptrdiff_t size = HASH_TABLE_SIZE (h); - ptrdiff_t *freq = xzalloc (size * sizeof *freq); + ptrdiff_t *freq = xcalloc (size, sizeof *freq); ptrdiff_t index_size = hash_table_index_size (h); for (ptrdiff_t i = 0; i < index_size; i++) { diff --git a/src/lisp.h b/src/lisp.h index bf80cfec3ad..d4978460f68 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -5536,6 +5536,8 @@ extern void *xmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)) ATTRIBUTE_RETURNS_NONNULL; extern void *xzalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)) ATTRIBUTE_RETURNS_NONNULL; +extern void *xcalloc (size_t, size_t) + ATTRIBUTE_MALLOC_SIZE ((1,2)) ATTRIBUTE_RETURNS_NONNULL; extern void *xrealloc (void *, size_t) ATTRIBUTE_ALLOC_SIZE ((2)) ATTRIBUTE_RETURNS_NONNULL; extern void xfree (void *); diff --git a/src/nsfns.m b/src/nsfns.m index efe622782f7..045d167e6b4 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2768,7 +2768,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) if (n_monitors == 0) return Qnil; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); for (i = 0; i < [screens count]; ++i) { diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4257dc45f98..e1766d2b1a6 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2432,7 +2432,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) gdpy = dpyinfo->gdpy; n_monitors = gdk_display_get_n_monitors (gdpy); monitor_frames = make_nil_vector (n_monitors); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); FOR_EACH_FRAME (rest, frame) { diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 425da3b8fd4..7e32252616b 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -213,7 +213,7 @@ pgtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, if (VECTORP (targets)) { - gtargets = xzalloc (sizeof *gtargets * ASIZE (targets)); + gtargets = xcalloc (ASIZE (targets), sizeof *gtargets); ntargets = 0; for (i = 0; i < ASIZE (targets); ++i) diff --git a/src/profiler.c b/src/profiler.c index 67049f487ee..b8339a3c544 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -75,21 +75,24 @@ make_log (int size, int depth) int index_size = size * 2 + 1; log->index_size = index_size; - log->trace = xmalloc (depth * sizeof *log->trace); + log->trace = xnmalloc (depth, sizeof *log->trace); - log->index = xmalloc (index_size * sizeof *log->index); + log->index = xnmalloc (index_size, sizeof *log->index); for (int i = 0; i < index_size; i++) log->index[i] = -1; - log->next = xmalloc (size * sizeof *log->next); + log->next = xnmalloc (size, sizeof *log->next); for (int i = 0; i < size - 1; i++) log->next[i] = i + 1; log->next[size - 1] = -1; log->next_free = 0; - log->hash = xmalloc (size * sizeof *log->hash); - log->keys = xzalloc (size * depth * sizeof *log->keys); - log->counts = xzalloc (size * sizeof *log->counts); + log->hash = xnmalloc (size, sizeof *log->hash); + size_t size_x_depth; + if (ckd_mul (&size_x_depth, size, depth)) + memory_full_up (); + log->keys = xcalloc (size_x_depth, sizeof *log->keys); + log->counts = xcalloc (size, sizeof *log->counts); return log; } diff --git a/src/sfnt.c b/src/sfnt.c index ab6a2d5e7bc..e46ebc3a08b 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -70,11 +70,11 @@ xmalloc (size_t size) } MAYBE_UNUSED static void * -xzalloc (size_t size) +xcalloc (ptrdiff_t n, ptrdiff_t s) { void *ptr; - ptr = calloc (1, size); + ptr = calloc (n, s); if (!ptr) abort (); @@ -111,6 +111,8 @@ xfree (void *ptr) /* Also necessary. */ #define AVOID _Noreturn ATTRIBUTE_COLD void +#define eassert(expr) assert (expr) + #else #define TEST_STATIC #include "lisp.h" @@ -5047,7 +5049,7 @@ sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges, sfnt_step_raster_proc proc, void *dcontext) { int y; - size_t size, e, edges_processed; + size_t e, edges_processed; struct sfnt_fedge *active, **prev, *a, sentinel; struct sfnt_step_raster raster; struct sfnt_step_chunk *next, *last; @@ -5065,11 +5067,7 @@ sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges, raster.scanlines = height; raster.chunks = NULL; - - if (ckd_mul (&size, height, sizeof *raster.steps)) - abort (); - - raster.steps = xzalloc (size); + raster.steps = xcalloc (height, sizeof *raster.steps); for (; y != height; y += 1) { diff --git a/src/treesit.c b/src/treesit.c index 3d342be3dcc..00b97da2c5c 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -559,19 +559,13 @@ load_tree_sitter_if_necessary (bool required) #endif } -static void * -treesit_calloc_wrapper (size_t n, size_t size) -{ - return xzalloc (n * size); -} - static void treesit_initialize (void) { if (!treesit_initialized) { load_tree_sitter_if_necessary (true); - ts_set_allocator (xmalloc, treesit_calloc_wrapper, xrealloc, xfree); + ts_set_allocator (xmalloc, xcalloc, xrealloc, xfree); treesit_initialized = true; } } diff --git a/src/xfns.c b/src/xfns.c index 7ec6025ab66..ba3bf211f55 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6254,7 +6254,7 @@ x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo) / x_display_pixel_width (dpyinfo)); mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen) / x_display_pixel_height (dpyinfo)); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); for (i = 0; i < n_monitors; ++i) { struct MonitorInfo *mi = &monitors[i]; @@ -6328,7 +6328,7 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) if (!rr_monitors) goto fallback; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); #ifdef USE_XCB atom_name_cookies = alloca (n_monitors * sizeof *atom_name_cookies); #endif @@ -6427,7 +6427,7 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) return Qnil; } n_monitors = resources->noutput; - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); #if RANDR13_LIBRARY if (randr13_avail) @@ -6644,7 +6644,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) / x_display_pixel_height (dpyinfo)); #endif monitor_frames = make_nil_vector (n_monitors); - monitors = xzalloc (n_monitors * sizeof *monitors); + monitors = xcalloc (n_monitors, sizeof *monitors); FOR_EACH_FRAME (rest, frame) { diff --git a/src/xterm.c b/src/xterm.c index 941297a77ce..06fe480646e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5730,7 +5730,7 @@ x_cache_xi_devices (struct x_display_info *dpyinfo) return; } - dpyinfo->devices = xzalloc (sizeof *dpyinfo->devices * ndevices); + dpyinfo->devices = xcalloc (ndevices, sizeof *dpyinfo->devices); for (i = 0; i < ndevices; ++i) { @@ -13881,7 +13881,7 @@ xi_disable_devices (struct x_display_info *dpyinfo, return; ndevices = 0; - devices = xzalloc (sizeof *devices * dpyinfo->num_devices); + devices = xcalloc (dpyinfo->num_devices, sizeof *devices); /* Loop through every device currently in DPYINFO, and copy it to DEVICES if it is not in TO_DISABLE. Note that this function |
