Evas masking: Fix potential invalid access to mask image

After clip_image_get, the old mask may be replaced by a new one,
and unref'ed, but it is later on set back as the context mask image.
Maybe it's possible that there was 0 reference and the image
got freed in between.

No idea how to test this.

@fix
This commit is contained in:
Jean-Philippe Andre 2015-08-31 17:28:58 +09:00
parent b6abbf1277
commit d69f9e0b84
5 changed files with 36 additions and 4 deletions

View File

@ -1559,6 +1559,8 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj,
e->engine.func->context_clip_unset(e->engine.data.output, context);
e->engine.func->context_clip_image_set
(e->engine.data.output, context, oldm_sfc, oldm_x, oldm_y, e, do_async);
/* unref image since clip_image_get refs it */
if (oldm_sfc) e->engine.func->image_free(e->engine.data.output, oldm_sfc);
}
// FIXME: needs to cache these maps and
@ -1694,6 +1696,8 @@ evas_render_mapped(Evas_Public_Data *e, Evas_Object *eo_obj,
e->engine.func->context_clip_unset(e->engine.data.output, ctx);
e->engine.func->context_clip_image_set
(e->engine.data.output, ctx, oldm_sfc, oldm_x, oldm_y, e, do_async);
/* unref image since clip_image_get refs it */
if (oldm_sfc) e->engine.func->image_free(e->engine.data.output, oldm_sfc);
}
if (!use_mapped_ctx)
e->engine.func->context_free(e->engine.data.output, ctx);

View File

@ -263,6 +263,9 @@ evas_filter_context_destroy(Evas_Filter_Context *ctx)
EINA_INLIST_FREE(ctx->commands, cmd)
_command_del(ctx, cmd);
if (ctx->target.mask)
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
free(ctx);
}
@ -1497,6 +1500,8 @@ Eina_Bool
evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
void *surface, int x, int y)
{
void *mask = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
ctx->target.bufid = evas_filter_buffer_image_new(ctx, surface);
@ -1513,7 +1518,10 @@ evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context,
ctx->target.color_use = EINA_FALSE;
ENFN->context_clip_image_get
(ENDT, draw_context, &ctx->target.mask, &ctx->target.mask_x, &ctx->target.mask_y);
(ENDT, draw_context, &mask, &ctx->target.mask_x, &ctx->target.mask_y);
if (ctx->target.mask)
ctx->evas->engine.func->image_free(ctx->evas->engine.data.output, ctx->target.mask);
ctx->target.mask = mask;
if (ctx->gl_engine)
{

View File

@ -1268,7 +1268,7 @@ struct _Evas_Func
void (*context_clip_set) (void *data, void *context, int x, int y, int w, int h);
void (*context_clip_image_set) (void *data, void *context, void *surface, int x, int y, Evas_Public_Data *evas, Eina_Bool do_async);
void (*context_clip_image_unset) (void *data, void *context);
void (*context_clip_image_get) (void *data, void *context, void **surface, int *x, int *y);
void (*context_clip_image_get) (void *data, void *context, void **surface, int *x, int *y); /* incref surface if not NULL */
void (*context_clip_clip) (void *data, void *context, int x, int y, int w, int h);
void (*context_clip_unset) (void *data, void *context);
int (*context_clip_get) (void *data, void *context, int *x, int *y, int *w, int *h);

View File

@ -2160,7 +2160,13 @@ eng_context_clip_image_get(void *data EINA_UNUSED, void *context, void **ie, int
{
RGBA_Draw_Context *ctx = context;
if (ie) *ie = ctx->clip.mask;
if (ie)
{
Evas_GL_Image *im = ctx->clip.mask;
*ie = im;
if (im) evas_gl_common_image_ref(im);
}
if (x) *x = ctx->clip.mask_x;
if (y) *y = ctx->clip.mask_y;
}

View File

@ -511,7 +511,21 @@ eng_context_clip_image_get(void *data EINA_UNUSED, void *context, void **ie, int
{
RGBA_Draw_Context *ctx = context;
if (ie) *ie = ctx->clip.mask;
if (ie)
{
Image_Entry *im = ctx->clip.mask;
*ie = im;
if (im)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_ref(im);
else
#endif
evas_cache_image_ref(im);
}
}
if (x) *x = ctx->clip.mask_x;
if (y) *y = ctx->clip.mask_y;
}