Evas masking: Avoid potential crashes (SW)

Make sure not to sample the mask image outside its boundaries.
This is a series of last resort checks. I can not reproduce the
crashes but know they have happened.

I used EINA_UNLIKELY more for clarity than for compiler optimizations.
This commit is contained in:
Jean-Philippe Andre 2015-04-08 17:21:42 +09:00
parent 9281fb5537
commit 464e6ca987
4 changed files with 89 additions and 15 deletions

View File

@ -534,6 +534,16 @@ evas_common_font_glyph_draw(RGBA_Font_Glyph *fg,
buf = alloca(sizeof(DATA32) * w * h);
// Adjust clipping info
if (EINA_UNLIKELY((x + x1) < dc->clip.mask_x))
x1 = dc->clip.mask_x - x;
if (EINA_UNLIKELY((y + y1) < dc->clip.mask_y))
y1 = dc->clip.mask_y - y;
if (EINA_UNLIKELY((x + x2) > (int)(x + x1 + im->cache_entry.w)))
x2 = x1 + im->cache_entry.w;
if (EINA_UNLIKELY((y + y2) > (int)(y + y1 + im->cache_entry.h)))
y2 = y1 + im->cache_entry.h;
// Step 1: alpha glyph drawing
src8 = evas_common_font_glyph_uncompress(fg, NULL, NULL);
if (!src8) return;

View File

@ -135,7 +135,18 @@ rectangle_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y, in
#endif
{
if (mask_ie)
func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst->cache_entry.flags.alpha, w, dc->render_op);
{
func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst->cache_entry.flags.alpha, w, dc->render_op);
// Adjust clipping info
if (EINA_UNLIKELY((x - dc->clip.mask_x) < 0))
x = dc->clip.mask_x;
if (EINA_UNLIKELY((y - dc->clip.mask_y) < 0))
y = dc->clip.mask_y;
if (EINA_UNLIKELY((x - dc->clip.mask_x + w) > (int)mask_ie->cache_entry.w))
w = mask_ie->cache_entry.w + dc->clip.mask_x - x;
if (EINA_UNLIKELY((y - dc->clip.mask_y + h) > (int)mask_ie->cache_entry.h))
h = mask_ie->cache_entry.h + dc->clip.mask_y - y;
}
else
func = evas_common_gfx_func_composite_color_span_get(dc->col.col, dst->cache_entry.flags.alpha, w, dc->render_op);
ptr = dst->image.data + (y * dst->cache_entry.w) + x;
@ -165,7 +176,18 @@ evas_common_rectangle_rgba_draw(RGBA_Image *dst, DATA32 color, int render_op, in
int yy;
if (mask_ie)
func = evas_common_gfx_func_composite_mask_color_span_get(color, dst->cache_entry.flags.alpha, w, render_op);
{
func = evas_common_gfx_func_composite_mask_color_span_get(color, dst->cache_entry.flags.alpha, w, render_op);
// Adjust clipping info
if (EINA_UNLIKELY((x - mask_x) < 0))
x = mask_x;
if (EINA_UNLIKELY((y - mask_y) < 0))
y = mask_y;
if (EINA_UNLIKELY((x - mask_x + w) > (int)mask_ie->cache_entry.w))
w = mask_ie->cache_entry.w + mask_x - x;
if (EINA_UNLIKELY((y - mask_y + h) > (int)mask_ie->cache_entry.h))
h = mask_ie->cache_entry.h + mask_y - y;
}
else
func = evas_common_gfx_func_composite_color_span_get(color, dst->cache_entry.flags.alpha, w, render_op);

View File

@ -131,7 +131,7 @@ _evas_common_scale_rgba_sample_scale_mask(int y,
int dst_clip_x, int dst_clip_y,
int dst_clip_w, int dst_clip_h, int dst_w,
int mask_x, int mask_y,
DATA32 **row_ptr, int *lin_ptr, RGBA_Image *im,
DATA32 **row_ptr, int *lin_ptr, RGBA_Image *mask_ie,
DATA32 *dptr, RGBA_Gfx_Func func, RGBA_Gfx_Func func2,
unsigned int mul_col)
{
@ -141,14 +141,24 @@ _evas_common_scale_rgba_sample_scale_mask(int y,
/* a scanline buffer */
buf = alloca(dst_clip_w * sizeof(DATA32));
// Adjust clipping info
if (EINA_UNLIKELY((dst_clip_x - mask_x) < 0))
dst_clip_x = mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y + y) < 0))
dst_clip_y = mask_y + y;
if (EINA_UNLIKELY((dst_clip_x - mask_x + dst_clip_w) > (int)mask_ie->cache_entry.w))
dst_clip_w = mask_x - mask_ie->cache_entry.w - dst_clip_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y + y + dst_clip_h) > (int)mask_ie->cache_entry.h))
dst_clip_h = mask_y + y - mask_ie->cache_entry.h - dst_clip_y;
dptr = dptr + dst_w * y;
for (; y < dst_clip_h; y++)
{
DATA8 *mask;
dst_ptr = buf;
mask = im->image.data8
+ ((dst_clip_y - mask_y + y) * im->cache_entry.w)
mask = mask_ie->image.data8
+ ((dst_clip_y - mask_y + y) * mask_ie->cache_entry.w)
+ (dst_clip_x - mask_x);
for (x = 0; x < dst_clip_w; x++)
@ -325,6 +335,15 @@ evas_common_scale_rgba_sample_draw(RGBA_Image *src, RGBA_Image *dst, int dst_cli
}
else
func = evas_common_gfx_func_composite_pixel_mask_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dst->cache_entry.flags.alpha, dst_clip_w, render_op);
// Adjust clipping info
if (EINA_UNLIKELY((dst_clip_x - mask_x) < 0))
dst_clip_x = mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y) < 0))
dst_clip_y = mask_y;
if (EINA_UNLIKELY((dst_clip_x - mask_x + dst_clip_w) > (int)mask_ie->cache_entry.w))
dst_clip_w = mask_ie->cache_entry.w - dst_clip_x + mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y + dst_clip_h) > (int)mask_ie->cache_entry.h))
dst_clip_h = mask_ie->cache_entry.h - dst_clip_y + mask_y;
}
if ((dst_region_w == src_region_w) && (dst_region_h == src_region_h))
@ -449,8 +468,9 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
DATA32 *ptr, *dst_ptr, *src_data, *dst_data;
DATA8 *mask;
int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
int src_w, src_h, dst_w, dst_h;
int src_w, src_h, dst_w, dst_h, mask_x, mask_y;
RGBA_Gfx_Func func, func2 = NULL;
RGBA_Image *mask_ie = dc->clip.mask;
if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
return EINA_FALSE;
@ -578,7 +598,7 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
/* figure out dest start ptr */
dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_w);
if (!dc->clip.mask)
if (!mask_ie)
{
if (dc->mul.use)
func = evas_common_gfx_func_composite_pixel_color_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dc->mul.col, dst->cache_entry.flags.alpha, dst_clip_w, dc->render_op);
@ -590,6 +610,17 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
func = evas_common_gfx_func_composite_pixel_mask_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dst->cache_entry.flags.alpha, dst_clip_w, dc->render_op);
if (dc->mul.use)
func2 = evas_common_gfx_func_composite_pixel_color_span_get(src->cache_entry.flags.alpha, src->cache_entry.flags.alpha_sparse, dc->mul.col, dst->cache_entry.flags.alpha, dst_clip_w, EVAS_RENDER_COPY);
// Adjust clipping info
mask_x = dc->clip.mask_x;
mask_y = dc->clip.mask_y;
if (EINA_UNLIKELY((dst_clip_x - mask_x) < 0))
dst_clip_x = mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y) < 0))
dst_clip_y = mask_y;
if (EINA_UNLIKELY((dst_clip_x - mask_x + dst_clip_w) > (int)mask_ie->cache_entry.w))
dst_clip_w = mask_ie->cache_entry.w - dst_clip_x + mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y + dst_clip_h) > (int)mask_ie->cache_entry.h))
dst_clip_h = mask_ie->cache_entry.h - dst_clip_y + mask_y;
}
if ((dst_region_w == src_region_w) && (dst_region_h == src_region_h))
@ -621,18 +652,16 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x;
/* image masking */
if (dc->clip.mask)
if (mask_ie)
{
RGBA_Image *im = dc->clip.mask;
if (dc->mul.use)
buf = alloca(dst_clip_w * sizeof(DATA32));
for (y = 0; y < dst_clip_h; y++)
{
mask = im->image.data8
+ ((dst_clip_y - dc->clip.mask_y + y) * im->cache_entry.w)
+ (dst_clip_x - dc->clip.mask_x);
mask = mask_ie->image.data8
+ ((dst_clip_y - mask_y + y) * mask_ie->cache_entry.w)
+ (dst_clip_x - mask_x);
/* * blend here [clip_w *] ptr -> dst_ptr * */
if (dc->mul.use)
@ -723,8 +752,8 @@ scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
local.dst_clip_h = dst_clip_h;
local.dst_clip_w = dst_clip_w;
local.dst_w = dst_w;
local.mask_x = dc->clip.mask_x;
local.mask_y = dc->clip.mask_y;
local.mask_x = mask_x;
local.mask_y = mask_y;
local.mul_col = mul_col;
msg = eina_thread_queue_send(thread_queue, sizeof (Evas_Scale_Msg), &ref);

View File

@ -131,6 +131,19 @@ SCALE_FUNC(RGBA_Image *src, RGBA_Image *dst, int dst_clip_x, int dst_clip_y, int
/* figure out dest start ptr */
dst_ptr = dst->image.data + dst_clip_x + (dst_clip_y * dst_w);
if (mask_ie)
{
// Adjust clipping info
if (EINA_UNLIKELY((dst_clip_x - mask_x) < 0))
dst_clip_x = mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y) < 0))
dst_clip_y = mask_y;
if (EINA_UNLIKELY((dst_clip_x - mask_x + dst_clip_w) > (int)mask_ie->cache_entry.w))
dst_clip_w = mask_ie->cache_entry.w - dst_clip_x + mask_x;
if (EINA_UNLIKELY((dst_clip_y - mask_y + dst_clip_h) > (int)mask_ie->cache_entry.h))
dst_clip_h = mask_ie->cache_entry.h - dst_clip_y + mask_y;
}
/* FIXME:
*
* things to do later for speedups: