Browse Source

canvas: fix an integer overflow in caca_resize().

Fixes: #52 (CVE-2021-3410)
tags/v0.99.beta20
Sam Hocevar 4 years ago
parent
commit
46b4ea7cea
3 changed files with 26 additions and 9 deletions
  1. +11
    -2
      caca/canvas.c
  2. +1
    -0
      caca/codec/import.c
  3. +14
    -7
      caca/codec/text.c

+ 11
- 2
caca/canvas.c View File

@@ -45,6 +45,7 @@ static int caca_resize(caca_canvas_t *, int, int);
* *
* If an error occurs, NULL is returned and \b errno is set accordingly: * If an error occurs, NULL is returned and \b errno is set accordingly:
* - \c EINVAL Specified width or height is invalid. * - \c EINVAL Specified width or height is invalid.
* - \c EOVERFLOW Specified width and height overflowed.
* - \c ENOMEM Not enough memory for the requested canvas size. * - \c ENOMEM Not enough memory for the requested canvas size.
* *
* \param width The desired canvas width * \param width The desired canvas width
@@ -200,6 +201,7 @@ int caca_unmanage_canvas(caca_canvas_t *cv, int (*callback)(void *), void *p)
* *
* If an error occurs, -1 is returned and \b errno is set accordingly: * If an error occurs, -1 is returned and \b errno is set accordingly:
* - \c EINVAL Specified width or height is invalid. * - \c EINVAL Specified width or height is invalid.
* - \c EOVERFLOW Specified width and height overflowed.
* - \c EBUSY The canvas is in use by a display driver and cannot be resized. * - \c EBUSY The canvas is in use by a display driver and cannot be resized.
* - \c ENOMEM Not enough memory for the requested canvas size. If this * - \c ENOMEM Not enough memory for the requested canvas size. If this
* happens, the canvas handle becomes invalid and should not be used. * happens, the canvas handle becomes invalid and should not be used.
@@ -363,7 +365,7 @@ int caca_rand(int min, int max)


int caca_resize(caca_canvas_t *cv, int width, int height) int caca_resize(caca_canvas_t *cv, int width, int height)
{ {
int x, y, f, old_width, old_height, new_size, old_size;
int x, y, f, old_width, old_height, old_size;


old_width = cv->width; old_width = cv->width;
old_height = cv->height; old_height = cv->height;
@@ -375,7 +377,14 @@ int caca_resize(caca_canvas_t *cv, int width, int height)
* dirty rectangle handling */ * dirty rectangle handling */
cv->width = width; cv->width = width;
cv->height = height; cv->height = height;
new_size = width * height;
int new_size = width * height;

/* Check for overflow */
if (new_size / width != height)
{
seterrno(EOVERFLOW);
return -1;
}


/* If width or height is smaller (or both), we have the opportunity to /* If width or height is smaller (or both), we have the opportunity to
* reduce or even remove dirty rectangles */ * reduce or even remove dirty rectangles */


+ 1
- 0
caca/codec/import.c View File

@@ -61,6 +61,7 @@ static ssize_t import_caca(caca_canvas_t *, void const *, size_t);
* *
* If an error occurs, -1 is returned and \b errno is set accordingly: * If an error occurs, -1 is returned and \b errno is set accordingly:
* - \c ENOMEM Not enough memory to allocate canvas. * - \c ENOMEM Not enough memory to allocate canvas.
* - \c EOVERFLOW Importing data caused a value overflow.
* - \c EINVAL Invalid format requested. * - \c EINVAL Invalid format requested.
* *
* \param cv A libcaca canvas in which to import the file. * \param cv A libcaca canvas in which to import the file.


+ 14
- 7
caca/codec/text.c View File

@@ -46,7 +46,7 @@ ssize_t _import_text(caca_canvas_t *cv, void const *data, size_t size)
char const *text = (char const *)data; char const *text = (char const *)data;
unsigned int width = 0, height = 0, x = 0, y = 0, i; unsigned int width = 0, height = 0, x = 0, y = 0, i;


caca_set_canvas_size(cv, width, height);
caca_set_canvas_size(cv, 0, 0);


for(i = 0; i < size; i++) for(i = 0; i < size; i++)
{ {
@@ -70,15 +70,19 @@ ssize_t _import_text(caca_canvas_t *cv, void const *data, size_t size)
if(y >= height) if(y >= height)
height = y + 1; height = y + 1;


caca_set_canvas_size(cv, width, height);
if (caca_set_canvas_size(cv, width, height) < 0)
return -1;
} }


caca_put_char(cv, x, y, ch); caca_put_char(cv, x, y, ch);
x++; x++;
} }


if(y > height)
caca_set_canvas_size(cv, width, height = y);
if (y > height)
{
if (caca_set_canvas_size(cv, width, height = y) < 0)
return -1;
}


return (ssize_t)size; return (ssize_t)size;
} }
@@ -431,7 +435,8 @@ ssize_t _import_ansi(caca_canvas_t *cv, void const *data, size_t size, int utf8)
{ {
savedattr = caca_get_attr(cv, -1, -1); savedattr = caca_get_attr(cv, -1, -1);
caca_set_attr(cv, im.clearattr); caca_set_attr(cv, im.clearattr);
caca_set_canvas_size(cv, width = x + wch, height);
if (caca_set_canvas_size(cv, width = x + wch, height) < 0)
return -1;
caca_set_attr(cv, savedattr); caca_set_attr(cv, savedattr);
} }
else else
@@ -448,7 +453,8 @@ ssize_t _import_ansi(caca_canvas_t *cv, void const *data, size_t size, int utf8)
caca_set_attr(cv, im.clearattr); caca_set_attr(cv, im.clearattr);
if(growy) if(growy)
{ {
caca_set_canvas_size(cv, width, height = y + 1);
if (caca_set_canvas_size(cv, width, height = y + 1) < 0)
return -1;
} }
else else
{ {
@@ -480,7 +486,8 @@ ssize_t _import_ansi(caca_canvas_t *cv, void const *data, size_t size, int utf8)
{ {
savedattr = caca_get_attr(cv, -1, -1); savedattr = caca_get_attr(cv, -1, -1);
caca_set_attr(cv, im.clearattr); caca_set_attr(cv, im.clearattr);
caca_set_canvas_size(cv, width, height = y);
if (caca_set_canvas_size(cv, width, height = y))
return -1;
caca_set_attr(cv, savedattr); caca_set_attr(cv, savedattr);
} }




Loading…
Cancel
Save