summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2026-05-23 17:55:11 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2026-05-23 19:18:54 -0700
commitc4e20777c26548722a37b03db93243e83a0d6188 (patch)
tree6c1bcc4e5e42e8dc2db32fd059f69dd20e558257
parent7e0d4fae01f2f1c7411297b1fb99ecdf82bfdea4 (diff)
Better size overflow checking for sfnt.c
* src/sfnt.c (memory_full_up) [TEST]: New static function. (xmalloc, xcalloc, xrealloc): Use it instead of aborting. (eassert) [TEST]: Remove; no longer needed. (xaddmalloc, xaddrealloc): New static convenience functions. (sfnt_read_cmap_format_12, sfnt_read_loca_table_short) (sfnt_read_loca_table_long, sfnt_read_glyf_table) (sfnt_read_simple_glyph, sfnt_read_compound_glyph) (sfnt_read_glyph, sfnt_build_append, sfnt_build_outline_edges) (sfnt_raster_glyph_outline, sfnt_build_outline_fedges) (sfnt_raster_glyph_outline_exact, sfnt_read_hmtx_table) (sfnt_read_name_table, sfnt_read_meta_table) (sfnt_read_ttc_header, sfnt_read_fpgm_table) (sfnt_read_prep_table, sfnt_create_uvs_context) (sfnt_read_gvar_table, sfnt_read_packed_deltas) (sfnt_vary_simple_glyph, sfnt_vary_compound_glyph): Use the new functions to test for size overflow more reliably. Use a cleaner way to decide whether a pointer addresses the heap not the stack and thus needs freeing. Fix a few more unlikely overflows. (sfnt_read_cmap_format_12): The recently-added eassert is no longer needed, so remove it. (sfnt_read_simple_glyph): Initialize glyph->simple early to simplify later code, as is done in similar functions. Complicate size test to avoid potential unsigned overflow.
-rw-r--r--src/sfnt.c278
1 files changed, 148 insertions, 130 deletions
diff --git a/src/sfnt.c b/src/sfnt.c
index 225b172cb40..5c3c2c4b972 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -56,6 +56,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
+static void
+memory_full_up (void)
+{
+ abort ();
+}
+
static void *
xmalloc (size_t size)
{
@@ -64,25 +70,40 @@ xmalloc (size_t size)
ptr = malloc (size);
if (!ptr)
- abort ();
+ memory_full_up ();
return ptr;
}
-MAYBE_UNUSED static void *
-xcalloc (ptrdiff_t n, ptrdiff_t s)
+static void *
+xcalloc (size_t n, size_t s)
{
void *ptr;
ptr = calloc (n, s);
if (!ptr)
- abort ();
+ memory_full_up ();
return ptr;
}
static void *
+xzalloc (size_t size)
+{
+ return xcalloc (1, size);
+}
+
+static void *
+xnmalloc (size_t n, size_t s)
+{
+ size_t size;
+ if (ckd_mul (&size, n, s))
+ memory_full_up ();
+ return xmalloc (size);
+}
+
+static void *
xrealloc (void *ptr, size_t size)
{
void *new_ptr;
@@ -90,7 +111,7 @@ xrealloc (void *ptr, size_t size)
new_ptr = realloc (ptr, size);
if (!new_ptr)
- abort ();
+ memory_full_up ();
return new_ptr;
}
@@ -111,13 +132,29 @@ xfree (void *ptr)
/* Also necessary. */
#define AVOID _Noreturn ATTRIBUTE_COLD void
-#define eassert(expr) assert (expr)
-
#else
#define TEST_STATIC
#include "lisp.h"
#endif
+static void *
+xaddmalloc (size_t base, size_t additional)
+{
+ size_t size;
+ if (ckd_add (&size, additional, base))
+ memory_full_up ();
+ return xmalloc (size);
+}
+
+static void *
+xaddrealloc (void *ptr, size_t base, size_t additional)
+{
+ size_t size;
+ if (ckd_add (&size, additional, base))
+ memory_full_up ();
+ return xrealloc (ptr, size);
+}
+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -738,8 +775,7 @@ sfnt_read_cmap_format_12 (int fd,
return NULL;
/* Allocate a buffer of sufficient size. */
- eassert (length < UINT32_MAX - sizeof *format12);
- format12 = xmalloc (length + sizeof *format12);
+ format12 = xaddmalloc (sizeof *format12, length);
format12->format = header->format;
format12->reserved = header->length;
format12->length = length;
@@ -1594,7 +1630,7 @@ sfnt_read_loca_table_short (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
/* Figure out how many glyphs there are based on the length. */
- loca = xmalloc (sizeof *loca + directory->length);
+ loca = xaddmalloc (sizeof *loca, directory->length);
loca->offsets = (uint16_t *) (loca + 1);
loca->num_offsets = directory->length / 2;
@@ -1639,7 +1675,7 @@ sfnt_read_loca_table_long (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
/* Figure out how many glyphs there are based on the length. */
- loca = xmalloc (sizeof *loca + directory->length);
+ loca = xaddmalloc (sizeof *loca, directory->length);
loca->offsets = (uint32_t *) (loca + 1);
loca->num_offsets = directory->length / 4;
@@ -1771,7 +1807,7 @@ sfnt_read_glyf_table (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
/* Allocate enough to hold everything. */
- glyf = xmalloc (sizeof *glyf + directory->length);
+ glyf = xaddmalloc (sizeof *glyf, directory->length);
glyf->size = directory->length;
glyf->glyphs = (unsigned char *) (glyf + 1);
@@ -1885,6 +1921,8 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
unsigned char *vec_start;
int16_t delta, x, y;
+ glyph->simple = NULL;
+
/* Calculate the minimum size of the glyph data. This is the size
of the instruction length field followed by
glyph->number_of_contours * sizeof (uint16_t). */
@@ -1893,14 +1931,11 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
+ sizeof (uint16_t));
/* Check that the size is big enough. */
- if (glyf->size < offset + min_size)
- {
- glyph->simple = NULL;
- return;
- }
+ if (glyf->size < min_size || glyf->size - min_size < offset)
+ return;
/* Allocate enough to read at least that. */
- simple = xmalloc (sizeof *simple + min_size);
+ simple = xaddmalloc (sizeof *simple, min_size);
simple->end_pts_of_contours = (uint16_t *) (simple + 1);
memcpy (simple->end_pts_of_contours, glyf->glyphs + offset,
min_size);
@@ -1928,16 +1963,15 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
else
number_of_points = 0;
- min_size_2 = (simple->instruction_length
- + number_of_points
- + (number_of_points
- * sizeof (uint16_t) * 2));
-
- /* Set simple->number_of_points. */
simple->number_of_points = number_of_points;
/* Make simple big enough. */
- simple = xrealloc (simple, sizeof *simple + min_size + min_size_2);
+ size_t size;
+ if (ckd_mul (&min_size_2, number_of_points, sizeof (uint16_t) * 2 + 1)
+ || ckd_add (&min_size_2, min_size_2, simple->instruction_length)
+ || ckd_add (&size, min_size, min_size_2))
+ memory_full_up ();
+ simple = xaddrealloc (simple, sizeof *simple, size);
simple->end_pts_of_contours = (uint16_t *) (simple + 1);
/* Set the instruction data pointer and other pointers.
@@ -1958,7 +1992,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
|| (instructions_start + simple->instruction_length
>= glyf->glyphs + glyf->size))
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -1973,7 +2006,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (flags_start >= glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -1997,7 +2029,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (flags_start + 1 >= glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2025,7 +2056,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (i != number_of_points)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2051,7 +2081,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (vec_start + 1 > glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2068,7 +2097,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (vec_start + 2 > glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2102,7 +2130,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (vec_start + 1 > glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2119,7 +2146,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
if (vec_start + 2 > glyf->glyphs + glyf->size)
{
- glyph->simple = NULL;
xfree (simple);
return;
}
@@ -2139,7 +2165,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
/* All done. */
simple->y_coordinates_end = simple->y_coordinates + i;
glyph->simple = simple;
- return;
}
/* Read the compound glyph outline from the glyph GLYPH from the
@@ -2209,8 +2234,7 @@ sfnt_read_compound_glyph (struct sfnt_glyph *glyph,
}
/* Now allocate the buffer to hold all the glyph data. */
- glyph->compound = xmalloc (sizeof *glyph->compound
- + required_bytes);
+ glyph->compound = xaddmalloc (sizeof *glyph->compound, required_bytes);
glyph->compound->components
= (struct sfnt_compound_glyph_component *) (glyph->compound + 1);
glyph->compound->num_components = num_components;
@@ -2431,9 +2455,8 @@ sfnt_read_glyph (sfnt_glyph glyph_code,
glyph.ymax = 0;
glyph.advance_distortion = 0;
glyph.origin_distortion = 0;
- glyph.simple = xmalloc (sizeof *glyph.simple);
+ glyph.simple = xzalloc (sizeof *glyph.simple);
glyph.compound = NULL;
- memset (glyph.simple, 0, sizeof *glyph.simple);
memory = xmalloc (sizeof *memory);
*memory = glyph;
return memory;
@@ -3608,17 +3631,19 @@ sfnt_build_append (int flags, sfnt_fixed x, sfnt_fixed y)
outline->outline_used++;
- /* See if the outline has to be extended. Checking for overflow
- should not be necessary. */
+ /* See if the outline has to be extended. */
if (outline->outline_used > outline->outline_size)
{
+ /* This can't overflow, as the old value did not overflow when
+ multiplied by sizeof *outline->outline. */
outline->outline_size = outline->outline_used * 2;
/* Extend the outline to some size past the new size. */
- outline = xrealloc (outline, (sizeof *outline
- + (outline->outline_size
- * sizeof *outline->outline)));
+ size_t size;
+ if (ckd_mul (&size, outline->outline_size, sizeof *outline->outline))
+ memory_full_up ();
+ outline = xaddrealloc (outline, sizeof *outline, size);
outline->outline
= (struct sfnt_glyph_outline_command *) (outline + 1);
}
@@ -4039,7 +4064,12 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline,
sfnt_fixed dx, dy, bot, step_x, ymin, xmin;
size_t top, bottom, y;
- edges = alloca (outline->outline_used * sizeof *edges);
+ void *edges_alloc = NULL;
+ if (outline->outline_used < 1024 * 16 / sizeof *edges)
+ edges = alloca (outline->outline_used * sizeof *edges);
+ else
+ edges = edges_alloc = xnmalloc (outline->outline_used, sizeof *edges);
+
edge = 0;
/* ymin and xmin must be the same as the offset used to set offy and
@@ -4132,6 +4162,7 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline,
if (edge)
edge_proc (edges, edge, dcontext);
+ xfree (edges_alloc);
}
/* Sort an array of SIZE edges to increase by bottom Y position, in
@@ -4484,11 +4515,15 @@ sfnt_raster_glyph_outline (struct sfnt_glyph_outline *outline)
/* Get the raster parameters. */
sfnt_prepare_raster (&raster, outline);
- /* Allocate the raster data. */
- data = xmalloc (sizeof *data + raster.stride * raster.height);
+ /* Allocate the raster data. Clear the raster; it is easier to use
+ xzalloc and clear everything. */
+ size_t size;
+ if (ckd_mul (&size, raster.stride, raster.height)
+ || ckd_add (&size, size, sizeof *data))
+ memory_full_up ();
+ data = xzalloc (size);
*data = raster;
data->cells = (unsigned char *) (data + 1);
- memset (data->cells, 0, raster.stride * raster.height);
/* Generate edges for the outline, polying each array of edges to
the raster. */
@@ -4688,7 +4723,12 @@ sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline,
sfnt_fixed dx, dy, step_x, step_y, ymin, xmin;
size_t top, bottom;
- edges = alloca (outline->outline_used * sizeof *edges);
+ void *edges_alloc = NULL;
+ if (outline->outline_used < 1024 * 16 / sizeof *edges)
+ edges = alloca (outline->outline_used * sizeof *edges);
+ else
+ edges = edges_alloc = xnmalloc (outline->outline_used, sizeof *edges);
+
edge = 0;
/* ymin and xmin must be the same as the offset used to set offy and
@@ -4773,6 +4813,7 @@ sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline,
if (edge)
edge_proc (edges, edge, dcontext);
+ xfree (edges_alloc);
}
typedef void (*sfnt_step_raster_proc) (struct sfnt_step_raster *, void *);
@@ -5376,15 +5417,21 @@ TEST_STATIC struct sfnt_raster *
sfnt_raster_glyph_outline_exact (struct sfnt_glyph_outline *outline)
{
struct sfnt_raster raster, *data;
+ size_t size;
/* Get the raster parameters. */
sfnt_prepare_raster (&raster, outline);
- /* Allocate the raster data. */
- data = xmalloc (sizeof *data + raster.stride * raster.height);
+ /* Allocate the raster data. Clear the raster; it is easier to use
+ xcalloc and clear everything. */
+ if (ckd_mul (&size, raster.stride, raster.height)
+ || ckd_add (&size, size, sizeof *data))
+ return NULL;
+ data = xcalloc (1, size);
+ if (!data)
+ return NULL;
*data = raster;
data->cells = (unsigned char *) (data + 1);
- memset (data->cells, 0, raster.stride * raster.height);
/* Generate edges for the outline, polying each array of edges to
the raster. */
@@ -5444,7 +5491,7 @@ sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable,
/* Now allocate enough to hold all of that along with the table
directory structure. */
- hmtx = xmalloc (sizeof *hmtx + size);
+ hmtx = xaddmalloc (sizeof *hmtx, size);
/* Read into hmtx + 1. */
rc = read (fd, hmtx + 1, size);
@@ -5591,13 +5638,9 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
if (directory->length < required)
return NULL;
- /* Avoid overflow in xmalloc argument below. */
- if (directory->length > UINT_MAX - sizeof *name)
- return NULL;
-
/* Allocate enough to hold the name table and variable length
data. */
- name = xmalloc (sizeof *name + directory->length);
+ name = xaddmalloc (sizeof *name, directory->length);
/* Read the fixed length data. */
rc = read (fd, name, required);
@@ -5671,10 +5714,11 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
- (name->count
* sizeof *name->name_records)))
{
- name = xrealloc (name, (sizeof *name
- + (name->count
- * sizeof *name->name_records)
- + required));
+ size_t size;
+ if (ckd_mul (&size, name->count, sizeof *name->name_records)
+ || ckd_add (&size, size, required))
+ memory_full_up ();
+ name = xaddrealloc (name, sizeof *name, size);
name->name_records = (struct sfnt_name_record *) (name + 1);
}
@@ -5801,7 +5845,7 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable)
if (ckd_mul (&map_size, sizeof *meta->data_maps, meta->num_data_maps)
/* Do so while checking for overflow from bad sfnt files. */
- || ckd_add (&data_size, map_size, sizeof *meta)
+ || directory->length - required < map_size
|| ckd_add (&data_size, data_size, directory->length))
{
xfree (meta);
@@ -5809,15 +5853,7 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable)
}
/* Do the reallocation. */
- meta = xrealloc (meta, data_size);
-
- /* Check that the remaining data is big enough to hold the data
- maps. */
- if (directory->length - required < map_size)
- {
- xfree (meta);
- return NULL;
- }
+ meta = xaddrealloc (meta, sizeof *meta, data_size);
/* Set pointers to data_maps and data. */
meta->data_maps = (struct sfnt_meta_data_map *) (meta + 1);
@@ -5945,7 +5981,7 @@ sfnt_read_ttc_header (int fd)
return NULL;
}
- ttc = xrealloc (ttc, sizeof *ttc + size);
+ ttc = xaddrealloc (ttc, sizeof *ttc, size);
ttc->offset_table = (uint32_t *) (ttc + 1);
rc = read (fd, ttc->offset_table, size);
if (rc == -1 || rc < size)
@@ -6113,7 +6149,7 @@ sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
/* Allocate enough for that much data. */
- fpgm = xmalloc (sizeof *fpgm + directory->length);
+ fpgm = xaddmalloc (sizeof *fpgm, directory->length);
/* Now set fpgm->num_instructions as appropriate, and make
fpgm->instructions point to the right place. */
@@ -6161,7 +6197,7 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
/* Allocate enough for that much data. */
- prep = xmalloc (sizeof *prep + directory->length);
+ prep = xaddmalloc (sizeof *prep, directory->length);
/* Now set prep->num_instructions as appropriate, and make
prep->instructions point to the right place. */
@@ -13498,22 +13534,17 @@ TEST_STATIC struct sfnt_uvs_context *
sfnt_create_uvs_context (struct sfnt_cmap_format_14 *cmap, int fd)
{
struct sfnt_table_offset_rec *table_offsets, *rec, template;
- size_t size, i, nmemb, j;
+ size_t i, nmemb, j;
off_t offset;
struct sfnt_uvs_context *context;
- if (ckd_mul (&size, cmap->num_var_selector_records,
- sizeof *table_offsets)
- || ckd_mul (&size, size, 2))
- return NULL;
-
context = NULL;
/* First, record and sort the UVS and nondefault UVS table offsets
in ascending order. */
- table_offsets = xmalloc (size);
- memset (table_offsets, 0, size);
+ table_offsets = xcalloc (cmap->num_var_selector_records,
+ 2 * sizeof *table_offsets);
nmemb = cmap->num_var_selector_records * 2;
j = 0;
@@ -14196,13 +14227,12 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
goto bail;
/* Figure out how big gvar needs to be. */
- if (ckd_add (&min_bytes, coordinate_size, sizeof *gvar)
- || ckd_add (&min_bytes, min_bytes, off_size)
+ if (ckd_add (&min_bytes, coordinate_size, off_size)
|| ckd_add (&min_bytes, min_bytes, data_size))
goto bail;
/* Now allocate enough for all of this extra data. */
- gvar = xrealloc (gvar, min_bytes);
+ gvar = xaddrealloc (gvar, sizeof *gvar, min_bytes);
/* Start reading offsets. */
@@ -14534,7 +14564,7 @@ sfnt_read_packed_deltas (unsigned char *restrict data,
if (data >= end)
return NULL;
- deltas = xmalloc (sizeof *deltas * n);
+ deltas = xnmalloc (n, sizeof *deltas);
i = 0;
while (i < n)
@@ -15326,7 +15356,7 @@ sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
{
size_t i, pair_start, pair_end, pair_first;
- pair_start = pair_first = -1;
+ pair_start = pair_first = SIZE_MAX;
/* Look for pairs of touched points. */
@@ -15335,7 +15365,7 @@ sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
if (!touched[i])
continue;
- if (pair_start == -1)
+ if (pair_start == SIZE_MAX)
{
pair_first = i;
goto next;
@@ -15538,10 +15568,11 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
/* Start reading each tuple. */
tuple = gvar->glyph_variation_data + offset + sizeof header;
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- coords = xmalloc (gvar->axis_count * sizeof *coords * 3);
- else
+ void *coords_alloc = NULL;
+ if (gvar->axis_count < 1024 * 16 / (3 * sizeof *coords))
coords = alloca (gvar->axis_count * sizeof *coords * 3);
+ else
+ coords = coords_alloc = xnmalloc (gvar->axis_count, 3 * sizeof *coords);
intermediate_start = coords + gvar->axis_count;
intermediate_end = intermediate_start + gvar->axis_count;
@@ -15551,6 +15582,8 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
touched = NULL;
original_x = NULL;
original_y = NULL;
+ void *touched_alloc = NULL;
+ void *original_x_alloc = NULL;
while (ntuples--)
{
@@ -15702,21 +15735,23 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
if (!original_x)
{
- if ((glyph->simple->number_of_points
- * sizeof *touched) >= 1024 * 16)
- touched = xmalloc (sizeof *touched
- * glyph->simple->number_of_points);
- else
+ if (glyph->simple->number_of_points
+ < 1024 * 16 / sizeof *touched)
touched = alloca (sizeof *touched
* glyph->simple->number_of_points);
-
- if ((sizeof *original_x * 2
- * glyph->simple->number_of_points) >= 1024 * 16)
- original_x = xmalloc (sizeof *original_x * 2
- * glyph->simple->number_of_points);
else
+ touched = touched_alloc
+ = xnmalloc (glyph->simple->number_of_points,
+ sizeof *touched);
+
+ if (glyph->simple->number_of_points
+ < 1024 * 16 / (2 * sizeof *original_x))
original_x = alloca (sizeof *original_x * 2
* glyph->simple->number_of_points);
+ else
+ original_x = original_x_alloc
+ = xnmalloc (glyph->simple->number_of_points,
+ 2 * sizeof *original_x);
original_y = original_x + glyph->simple->number_of_points;
}
@@ -15777,16 +15812,9 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
/* Return success. */
- if ((glyph->simple->number_of_points
- * sizeof *touched) >= 1024 * 16)
- xfree (touched);
-
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- xfree (coords);
-
- if ((sizeof *original_x * 2
- * glyph->simple->number_of_points) >= 1024 * 16)
- xfree (original_x);
+ xfree (touched_alloc);
+ xfree (coords_alloc);
+ xfree (original_x_alloc);
if (points != (uint16_t *) -1)
xfree (points);
@@ -15803,16 +15831,9 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
xfree (local_points);
fail1:
- if ((glyph->simple->number_of_points
- * sizeof *touched) >= 1024 * 16)
- xfree (touched);
-
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- xfree (coords);
-
- if ((sizeof *original_x * 2
- * glyph->simple->number_of_points) >= 1024 * 16)
- xfree (original_x);
+ xfree (touched_alloc);
+ xfree (coords_alloc);
+ xfree (original_x_alloc);
if (points != (uint16_t *) -1)
xfree (points);
@@ -15916,10 +15937,11 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id,
/* Start reading each tuple. */
tuple = gvar->glyph_variation_data + offset + sizeof header;
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- coords = xmalloc (gvar->axis_count * sizeof *coords * 3);
- else
+ void *coords_alloc = NULL;
+ if (gvar->axis_count < 1024 * 16 / (3 * sizeof *coords))
coords = alloca (gvar->axis_count * sizeof *coords * 3);
+ else
+ coords = coords_alloc = xnmalloc (gvar->axis_count, 3 * sizeof *coords);
intermediate_start = coords + gvar->axis_count;
intermediate_end = intermediate_start + gvar->axis_count;
@@ -16157,9 +16179,7 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id,
/* Return success. */
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- xfree (coords);
-
+ xfree (coords_alloc);
if (points != (uint16_t *) -1)
xfree (points);
@@ -16175,9 +16195,7 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id,
xfree (local_points);
fail1:
- if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16)
- xfree (coords);
-
+ xfree (coords_alloc);
if (points != (uint16_t *) -1)
xfree (points);