From: Tony Cook Date: Thu, 10 Jan 2019 12:24:43 +0000 (+1100) Subject: i_circle_aa_low() could buffer overflow X-Git-Tag: v1.009~2 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/1456b64519287552f971008818a4e8034cb27f14 i_circle_aa_low() could buffer overflow prevent it. It still needs some work for other reasons. --- diff --git a/Changes b/Changes index 6b0795f6..d9f2aeca 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,11 @@ Imager release history. Older releases can be found in Changes.old +Critical issue: + + - drawing a filled, anti-aliased circle to the left or right of the + image (not within the image at all) would cause a buffer overflow. + https://rt.cpan.org/Ticket/Display.html?id=128208 + General changes: - to_paletted() and make_palette() now fail (with an error in diff --git a/draw.c b/draw.c index e66af531..647c9d25 100644 --- a/draw.c +++ b/draw.c @@ -500,8 +500,11 @@ i_circle_aa_low(i_img *im, double x, double y, double rad, flush_render_t r, i_color temp; i_img_dim ly; dIMCTXim(im); - i_img_dim first_row = floor(y) - ceil(rad); - i_img_dim last_row = ceil(y) + ceil(rad); + double ceil_rad = ceil(rad); + i_img_dim first_row = floor(y) - ceil_rad; + i_img_dim last_row = ceil(y) + ceil_rad; + i_img_dim first_col = floor(x) - ceil_rad; + i_img_dim last_col = ceil(x) + ceil_rad; double r_sqr = rad * rad; i_img_dim max_width = 2 * ceil(rad) + 1; unsigned char *coverage = NULL; @@ -515,8 +518,12 @@ i_circle_aa_low(i_img *im, double x, double y, double rad, flush_render_t r, first_row = 0; if (last_row > im->ysize-1) last_row = im->ysize - 1; + if (first_col < 0) + first_col = 0; + if (last_col > im->xsize-1) + last_col = im->xsize - 1; - if (rad <= 0 || last_row < first_row) { + if (rad <= 0 || last_row < first_row || last_col < first_col) { /* outside the image */ return; } @@ -527,9 +534,9 @@ i_circle_aa_low(i_img *im, double x, double y, double rad, flush_render_t r, for(ly = first_row; ly < last_row; ly++) { frac min_frac_x[16]; frac max_frac_x[16]; - i_img_dim min_frac_left_x = im->xsize * 16; + i_img_dim min_frac_left_x = 16 *(ceil(x) + ceil(rad)); i_img_dim max_frac_left_x = -1; - i_img_dim min_frac_right_x = im->xsize * 16; + i_img_dim min_frac_right_x = 16 * (floor(x) - ceil(rad)); i_img_dim max_frac_right_x = -1; /* reset work_y each row so the error doesn't build up */ double work_y = ly; diff --git a/t/250-draw/010-draw.t b/t/250-draw/010-draw.t index 138786f1..b84f648f 100644 --- a/t/250-draw/010-draw.t +++ b/t/250-draw/010-draw.t @@ -1,6 +1,6 @@ #!perl -w use strict; -use Test::More tests => 256; +use Test::More; use Imager ':all'; use Imager::Test qw(is_color3 is_image); use constant PI => 3.14159265358979; @@ -137,6 +137,13 @@ my $white = '#FFFFFF'; "saving output"); } +{ + # RT #128208 + my $im = Imager->new(xsize => 200, ysize => 200); + ok($im->circle(aa => 1, color => "#FFF", r => 400, x => 1_000_000, y => 100, filled => 1), + "draw a very large circle"); +} + { my $im = Imager->new(xsize => 400, ysize => 400); ok($im->arc(x => 200, y => 202, r => 10, filled => 0), @@ -320,6 +327,7 @@ my $white = '#FFFFFF'; is($empty->errstr, "flood_fill: empty input image", "check error message"); } +done_testing(); malloc_state();