From: cedric Date: Wed, 14 Dec 2011 11:17:09 +0000 (+0000) Subject: evas: use Eina_File for wbmp code and fix a potential race condition at the same... X-Git-Tag: accepted/2.0/20130306.225542~155^2~84 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3c64de705a28d4ef5cddc6c79777c973abdf5baf;p=profile%2Fivi%2Fevas.git evas: use Eina_File for wbmp code and fix a potential race condition at the same time. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@66187 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/ChangeLog b/ChangeLog index c564bae..e43f6dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -558,4 +558,5 @@ 2011-12-14 Cedric BAIL - * Use Eina_File when loading bmp, ico and pmaps files. + * Use Eina_File when loading bmp, ico, pmaps and wbmp files. + * Fix potential race condition in wbmp loader code. diff --git a/NEWS b/NEWS index b6e0c03..8a217ca 100644 --- a/NEWS +++ b/NEWS @@ -9,7 +9,7 @@ Additions: Improvements: - * Use Eina_File mmap infrastructure for bmp, ico and pmaps file access. + * Use Eina_File mmap infrastructure for bmp, ico, pmaps and wbmp file access. Evas 1.1.0 diff --git a/src/modules/loaders/wbmp/evas_image_load_wbmp.c b/src/modules/loaders/wbmp/evas_image_load_wbmp.c index 70cb0bf..54e28d5 100644 --- a/src/modules/loaders/wbmp/evas_image_load_wbmp.c +++ b/src/modules/loaders/wbmp/evas_image_load_wbmp.c @@ -25,16 +25,16 @@ static Evas_Image_Load_Func evas_image_load_wbmp_func = static int -read_mb(unsigned int *data, FILE *f) +read_mb(unsigned int *data, void *map, size_t length, size_t *position) { int ac = 0, ct; unsigned char buf; - + for (ct = 0;;) { if ((ct++) == 5) return -1; - if ((fread(&buf, 1, 1, f)) < 1) - return -1; + if (*position > length) return -1; + buf = ((unsigned char *) map)[(*position)++]; ac = (ac << 7) | (buf & 0x7f); if ((buf & 0x80) == 0) break; } @@ -45,70 +45,105 @@ read_mb(unsigned int *data, FILE *f) static Eina_Bool evas_image_load_file_head_wbmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) { - FILE *f; + Eina_File *f; + void *map = NULL; + size_t position = 0; + size_t length; unsigned int type, w, h; - unsigned char fixed_header; - struct stat statbuf; - + *error = EVAS_LOAD_ERROR_GENERIC; - f = fopen(file, "rb"); + f = eina_file_open(file, 0); if (!f) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } - - if (stat(file, &statbuf) == -1) goto bail; - if (read_mb(&type, f) < 0) goto bail; - + + length = eina_file_size_get(f); + if (length <= 4) goto bail; + + map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + if (!map) goto bail; + + if (read_mb(&type, map, length, &position) < 0) goto bail; + if (type != 0) { *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; goto bail; } - - if (fread(&fixed_header, 1, 1, f) != 1) goto bail; - if (read_mb(&w, f) < 0) goto bail; - if (read_mb(&h, f) < 0) goto bail; + + position++; /* skipping one byte */ + if (read_mb(&w, map, length, &position) < 0) goto bail; + if (read_mb(&h, map, length, &position) < 0) goto bail; if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || IMG_TOO_BIG(w, h)) { *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto bail; } - - fclose(f); + + eina_file_map_free(f, map); + eina_file_close(f); ie->w = w; ie->h = h; - + *error = EVAS_LOAD_ERROR_NONE; return EINA_TRUE; bail: - fclose(f); + if (map) eina_file_map_free(f, map); + eina_file_close(f); return EINA_FALSE; } static Eina_Bool evas_image_load_file_data_wbmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) { - FILE *f; - unsigned int dummy, line_length; + Eina_File *f; + void *map = NULL; + size_t position = 0; + size_t length; + unsigned int type, w, h; + unsigned int line_length; unsigned char *line = NULL; int cur = 0, x, y; DATA32 *dst_data; - + *error = EVAS_LOAD_ERROR_GENERIC; - f = fopen(file, "rb"); + f = eina_file_open(file, EINA_FALSE); if (!f) { *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; return EINA_FALSE; } - if (read_mb(&dummy, f) < 0) goto bail; - if (fread(&dummy, 1, 1, f) != 1) goto bail; - if (read_mb(&dummy, f) < 0) goto bail; - if (read_mb(&dummy, f) < 0) goto bail; - + + length = eina_file_size_get(f); + if (length <= 4) goto bail; + + map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + if (!map) goto bail; + + if (read_mb(&type, map, length, &position) < 0) goto bail; + position++; /* skipping one byte */ + if (read_mb(&w, map, length, &position) < 0) goto bail; + if (read_mb(&h, map, length, &position) < 0) goto bail; + + if (type != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto bail; + } + + if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) || + IMG_TOO_BIG(w, h)) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto bail; + } + + ie->w = w; + ie->h = h; + evas_cache_image_surface_alloc(ie, ie->w, ie->h); dst_data = evas_cache_image_pixels(ie); if (!dst_data) @@ -116,13 +151,14 @@ evas_image_load_file_data_wbmp(Image_Entry *ie, const char *file, const char *ke *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; goto bail; } - + line_length = (ie->w + 7) >> 3; - line = alloca(line_length); - + for (y = 0; y < (int)ie->h; y++) { - if (fread(line, 1, line_length, f) != line_length) goto bail; + if (position + line_length > length) goto bail; + line = ((unsigned char*) map) + position; + position += line_length; for (x = 0; x < (int)ie->w; x++) { int idx = x >> 3; @@ -132,11 +168,13 @@ evas_image_load_file_data_wbmp(Image_Entry *ie, const char *file, const char *ke cur++; } } - fclose(f); + eina_file_map_free(f, map); + eina_file_close(f); *error = EVAS_LOAD_ERROR_NONE; return EINA_TRUE; bail: - fclose(f); + if (map) eina_file_map_free(f, map); + eina_file_close(f); return EINA_FALSE; }