From 96ff990d5e7cda59c73ab1d5bb77ff0c6e3b34f3 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 19 Oct 2021 15:25:54 +0200 Subject: [PATCH] Better sanity checks when creating 2D buffers (Closes #43) --- caca/caca.c | 11 +++++++++++ caca/caca_internals.h | 3 +++ caca/driver/cocoa.m | 6 +++--- caca/driver/win32.c | 3 +-- caca/font.c | 2 +- caca/transform.c | 16 ++++++++-------- ruby/caca-canvas.c | 2 +- src/common-image.c | 18 +++++++++--------- 8 files changed, 37 insertions(+), 24 deletions(-) diff --git a/caca/caca.c b/caca/caca.c index ae667ec..ddcb92e 100644 --- a/caca/caca.c +++ b/caca/caca.c @@ -280,6 +280,17 @@ char const * caca_get_version(void) return PACKAGE_VERSION; } +/* + * XXX: The following functions are private. + */ + +extern void *_caca_alloc2d(size_t width, size_t height, size_t elem_size) +{ + if (width == 0 || height == 0 || elem_size == 0 || SIZE_MAX / width / height < elem_size) + return NULL; + return malloc(width * height * elem_size); +} + /* * XXX: The following functions are local. */ diff --git a/caca/caca_internals.h b/caca/caca_internals.h index 84d790b..40b455c 100644 --- a/caca/caca_internals.h +++ b/caca/caca_internals.h @@ -259,6 +259,9 @@ extern int _pop_event(caca_display_t *, caca_privevent_t *); /* Internal window functions */ extern void _caca_set_term_title(char const *); +/* Internal memory function */ +extern void *_caca_alloc2d(size_t width, size_t height, size_t elem_size); + /* Profiling functions */ #if defined PROF extern void _caca_dump_stats(void); diff --git a/caca/driver/cocoa.m b/caca/driver/cocoa.m index 86c8a63..a72b86b 100644 --- a/caca/driver/cocoa.m +++ b/caca/driver/cocoa.m @@ -204,15 +204,15 @@ static BOOL s_quitting = NO; if(_attrs) free(_attrs); - _attrs = malloc(_w * _h * sizeof(uint32_t) * 2); + _attrs = _caca_alloc2d(_w , _h, sizeof(uint32_t) * 2); if(_bkg_rects) free(_bkg_rects); - _bkg_rects = malloc(_w * _h * sizeof(NSRect)); + _bkg_rects = _caca_alloc2d(_w, _h, sizeof(NSRect)); if(_bkg_colors) free(_bkg_colors); - _bkg_colors = malloc(_w * _h * sizeof(NSColor*)); + _bkg_colors = _caca_alloc2d(_w, _h, sizeof(NSColor*)); // [[self window] setContentSize: NSMakeSize(caca_get_canvas_width(dp->cv) * _font_rect.size.width, // caca_get_canvas_height(dp->cv) * _font_rect.size.height)]; diff --git a/caca/driver/win32.c b/caca/driver/win32.c index 7e26707..2439a97 100644 --- a/caca/driver/win32.c +++ b/caca/driver/win32.c @@ -166,8 +166,7 @@ static int win32_init_graphics(caca_display_t *dp) SetConsoleActiveScreenBuffer(dp->drv.p->screen); - dp->drv.p->buffer = malloc(width * height - * sizeof(CHAR_INFO)); + dp->drv.p->buffer = _caca_alloc2d(width, height, sizeof(CHAR_INFO)); if(dp->drv.p->buffer == NULL) return -1; diff --git a/caca/font.c b/caca/font.c index c898ea0..a7ce7bc 100644 --- a/caca/font.c +++ b/caca/font.c @@ -425,7 +425,7 @@ int caca_render_canvas(caca_canvas_t const *cv, caca_font_t const *f, } if(f->header.bpp != 8) - glyph = malloc(f->header.width * 2 * f->header.height); + glyph = _caca_alloc2d(f->header.width, f->header.height, 2); if(width < cv->width * f->header.width) xmax = width / f->header.width; diff --git a/caca/transform.c b/caca/transform.c index 408ae19..a8c7457 100644 --- a/caca/transform.c +++ b/caca/transform.c @@ -269,14 +269,14 @@ int caca_rotate_left(caca_canvas_t *cv) w2 = (cv->width + 1) / 2; h2 = cv->height; - newchars = malloc(w2 * h2 * 2 * sizeof(uint32_t)); + newchars = _caca_alloc2d(w2, h2, 2 * sizeof(uint32_t)); if(!newchars) { seterrno(ENOMEM); return -1; } - newattrs = malloc(w2 * h2 * 2 * sizeof(uint32_t)); + newattrs = _caca_alloc2d(w2, h2, 2 * sizeof(uint32_t)); if(!newattrs) { free(newchars); @@ -389,14 +389,14 @@ int caca_rotate_right(caca_canvas_t *cv) w2 = (cv->width + 1) / 2; h2 = cv->height; - newchars = malloc(w2 * h2 * 2 * sizeof(uint32_t)); + newchars = _caca_alloc2d(w2 * 2, h2, sizeof(uint32_t)); if(!newchars) { seterrno(ENOMEM); return -1; } - newattrs = malloc(w2 * h2 * 2 * sizeof(uint32_t)); + newattrs = _caca_alloc2d(w2 * 2, h2, sizeof(uint32_t)); if(!newattrs) { free(newchars); @@ -504,14 +504,14 @@ int caca_stretch_left(caca_canvas_t *cv) /* Save the current frame shortcuts */ _caca_save_frame_info(cv); - newchars = malloc(cv->width * cv->height * sizeof(uint32_t)); + newchars = _caca_alloc2d(cv->width, cv->height, sizeof(uint32_t)); if(!newchars) { seterrno(ENOMEM); return -1; } - newattrs = malloc(cv->width * cv->height * sizeof(uint32_t)); + newattrs = _caca_alloc2d(cv->width, cv->height, sizeof(uint32_t)); if(!newattrs) { free(newchars); @@ -597,14 +597,14 @@ int caca_stretch_right(caca_canvas_t *cv) /* Save the current frame shortcuts */ _caca_save_frame_info(cv); - newchars = malloc(cv->width * cv->height * sizeof(uint32_t)); + newchars = _caca_alloc2d(cv->width, cv->height, sizeof(uint32_t)); if(!newchars) { seterrno(ENOMEM); return -1; } - newattrs = malloc(cv->width * cv->height * sizeof(uint32_t)); + newattrs = _caca_alloc2d(cv->width, cv->height, sizeof(uint32_t)); if(!newattrs) { free(newchars); diff --git a/ruby/caca-canvas.c b/ruby/caca-canvas.c index 43a3ad4..a55fe60 100644 --- a/ruby/caca-canvas.c +++ b/ruby/caca-canvas.c @@ -583,7 +583,7 @@ static VALUE render_canvas(VALUE self, VALUE font, VALUE width, VALUE height, VA rb_raise(rb_eArgError, "First argument is not a Caca::Font"); } - buf = malloc(width*height*4); + buf = _caca_alloc2d(width, height, 4); if(buf == NULL) { rb_raise(rb_eNoMemError, "Out of memory"); diff --git a/src/common-image.c b/src/common-image.c index 43e756c..584b846 100644 --- a/src/common-image.c +++ b/src/common-image.c @@ -103,6 +103,14 @@ struct image * load_image(char const * name) uint32_t bpp = u16fread(f); uint32_t colors = 0; + /* Sanity check */ + if (planes != 1) + { + caca_file_close(f); + free(im); + return NULL; + } + if (header_size == 40) { if (u32fread(f) != 0) /* compression */ @@ -152,16 +160,8 @@ struct image * load_image(char const * name) uint32_t depth = (bpp + 7) / 8; - /* Sanity check */ - if (!depth || !im->w || im->w > 0x10000 || !im->h || im->h > 0x10000 || planes != 1) - { - caca_file_close(f); - free(im); - return NULL; - } - /* Allocate the pixel buffer */ - im->pixels = malloc(im->w * im->h * depth); + im->pixels = _caca_alloc2d(im->w, im->h, depth); if (!im->pixels) { caca_file_close(f);