forked from enlightenment/efl
evas/cserve2: prevent unwanted remap of strings table
In the client, string_get() can cause a remapping of the strings index & mempool. This means that all pointers to string data are invalid past that call. Solution: add a safe_get() function that prevents remap during search. It might prove faster also, but will return NULL more often.
This commit is contained in:
parent
745b4d4acc
commit
ffa27c7082
|
@ -74,9 +74,11 @@ static Eina_Hash *_file_entries = NULL;
|
||||||
// Shared index table
|
// Shared index table
|
||||||
static Index_Table _index;
|
static Index_Table _index;
|
||||||
static const char *_shared_string_get(int id);
|
static const char *_shared_string_get(int id);
|
||||||
|
static const char *_shared_string_safe_get(int id); // Do not allow remap during search
|
||||||
|
static Eina_Bool _string_index_refresh(void);
|
||||||
static int _server_index_list_set(Msg_Base *data, int size);
|
static int _server_index_list_set(Msg_Base *data, int size);
|
||||||
static const File_Data *_shared_file_data_get_by_id(unsigned int id);
|
static const File_Data *_shared_file_data_get_by_id(unsigned int id);
|
||||||
static const Shm_Object *_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id);
|
static const Shm_Object *_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id, Eina_Bool safe);
|
||||||
static const File_Data *_shared_image_entry_file_data_find(Image_Entry *ie);
|
static const File_Data *_shared_image_entry_file_data_find(Image_Entry *ie);
|
||||||
static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie);
|
static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie);
|
||||||
static const Font_Data *_shared_font_entry_data_find(Font_Entry *fe);
|
static const Font_Data *_shared_font_entry_data_find(Font_Entry *fe);
|
||||||
|
@ -1788,6 +1790,7 @@ _font_entry_glyph_map_rebuild_check(Font_Entry *fe, Font_Hint_Flags hints)
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
const char *idxpath = NULL, *datapath = NULL;
|
const char *idxpath = NULL, *datapath = NULL;
|
||||||
|
|
||||||
|
_string_index_refresh();
|
||||||
if (!fe->map)
|
if (!fe->map)
|
||||||
{
|
{
|
||||||
const Font_Data *fd;
|
const Font_Data *fd;
|
||||||
|
@ -1795,8 +1798,8 @@ _font_entry_glyph_map_rebuild_check(Font_Entry *fe, Font_Hint_Flags hints)
|
||||||
fd = _shared_font_entry_data_find(fe);
|
fd = _shared_font_entry_data_find(fe);
|
||||||
if (!fd) return -1;
|
if (!fd) return -1;
|
||||||
|
|
||||||
idxpath = _shared_string_get(fd->glyph_index_shm);
|
idxpath = _shared_string_safe_get(fd->glyph_index_shm);
|
||||||
datapath = _shared_string_get(fd->mempool_shm);
|
datapath = _shared_string_safe_get(fd->mempool_shm);
|
||||||
if (!idxpath || !datapath) return -1;
|
if (!idxpath || !datapath) return -1;
|
||||||
|
|
||||||
fe->map =_glyph_map_open(fe, idxpath, datapath);
|
fe->map =_glyph_map_open(fe, idxpath, datapath);
|
||||||
|
@ -2527,7 +2530,7 @@ _server_index_list_set(Msg_Base *data, int size)
|
||||||
|
|
||||||
// FIXME: (almost) copy & paste from evas_cserve2_cache.c
|
// FIXME: (almost) copy & paste from evas_cserve2_cache.c
|
||||||
static const char *
|
static const char *
|
||||||
_shared_string_get(int id)
|
_shared_string_internal_get(int id, Eina_Bool safe)
|
||||||
{
|
{
|
||||||
Index_Entry *ie;
|
Index_Entry *ie;
|
||||||
|
|
||||||
|
@ -2538,19 +2541,20 @@ _shared_string_get(int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
ie = (Index_Entry *)
|
ie = (Index_Entry *)
|
||||||
_shared_index_item_get_by_id(&_index.strings_index, sizeof(*ie), id);
|
_shared_index_item_get_by_id(&_index.strings_index, sizeof(*ie), id, safe);
|
||||||
if (!ie) return NULL;
|
if (!ie) return NULL;
|
||||||
if (ie->offset < 0) return NULL;
|
if (ie->offset < 0) return NULL;
|
||||||
if (!ie->refcount) return NULL;
|
if (!ie->refcount) return NULL;
|
||||||
if (ie->offset + ie->length > _index.strings_entries.size)
|
if (ie->offset + ie->length > _index.strings_entries.size)
|
||||||
{
|
{
|
||||||
|
if (safe) return NULL;
|
||||||
if (eina_file_refresh(_index.strings_entries.f)
|
if (eina_file_refresh(_index.strings_entries.f)
|
||||||
|| (_index.strings_entries.size != (int) eina_file_size_get(_index.strings_entries.f)))
|
|| (_index.strings_entries.size != (int) eina_file_size_get(_index.strings_entries.f)))
|
||||||
{
|
{
|
||||||
DBG("String entries size has changed from %d to %d",
|
DBG("String entries size has changed from %d to %d",
|
||||||
_index.strings_entries.size, (int) eina_file_size_get(_index.strings_entries.f));
|
_index.strings_entries.size, (int) eina_file_size_get(_index.strings_entries.f));
|
||||||
if (_string_index_refresh())
|
if (_string_index_refresh())
|
||||||
return _shared_string_get(id);
|
return _shared_string_internal_get(id, EINA_FALSE);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2558,6 +2562,18 @@ _shared_string_get(int id)
|
||||||
return _index.strings_entries.data + ie->offset;
|
return _index.strings_entries.data + ie->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
_shared_string_safe_get(int id)
|
||||||
|
{
|
||||||
|
return _shared_string_internal_get(id, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
_shared_string_get(int id)
|
||||||
|
{
|
||||||
|
return _shared_string_internal_get(id, EINA_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
#define SHARED_INDEX_CHECK(si, typ) \
|
#define SHARED_INDEX_CHECK(si, typ) \
|
||||||
do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \
|
do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \
|
||||||
CRIT("Failed to remap index"); return NULL; } } while (0)
|
CRIT("Failed to remap index"); return NULL; } } while (0)
|
||||||
|
@ -2597,6 +2613,7 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
|
||||||
return fdata;
|
return fdata;
|
||||||
|
|
||||||
// Scan shared index
|
// Scan shared index
|
||||||
|
_string_index_refresh();
|
||||||
for (k = _index.files.last_entry_in_hash;
|
for (k = _index.files.last_entry_in_hash;
|
||||||
k < _index.files.count && k < _index.files.header->emptyidx; k++)
|
k < _index.files.count && k < _index.files.header->emptyidx; k++)
|
||||||
{
|
{
|
||||||
|
@ -2609,8 +2626,8 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
|
||||||
if (!fd->id) break;
|
if (!fd->id) break;
|
||||||
if (!fd->refcount) continue;
|
if (!fd->refcount) continue;
|
||||||
|
|
||||||
key = _shared_string_get(fd->key);
|
key = _shared_string_safe_get(fd->key);
|
||||||
file = _shared_string_get(fd->path);
|
file = _shared_string_safe_get(fd->path);
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
ERR("Could not find filename for file %d: path id: %d",
|
ERR("Could not find filename for file %d: path id: %d",
|
||||||
|
@ -2619,11 +2636,6 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The strings base pointer may change if the index grows
|
|
||||||
if ((key < _index.strings_entries.data) ||
|
|
||||||
(key > _index.strings_entries.data + _index.strings_entries.size))
|
|
||||||
key = _shared_string_get(fd->key);
|
|
||||||
|
|
||||||
lo.region.x = fd->lo.region.x;
|
lo.region.x = fd->lo.region.x;
|
||||||
lo.region.y = fd->lo.region.y;
|
lo.region.y = fd->lo.region.y;
|
||||||
lo.region.w = fd->lo.region.w;
|
lo.region.w = fd->lo.region.w;
|
||||||
|
@ -2650,7 +2662,8 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Shm_Object *
|
static const Shm_Object *
|
||||||
_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id)
|
_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id,
|
||||||
|
Eina_Bool safe)
|
||||||
{
|
{
|
||||||
const Shm_Object *obj;
|
const Shm_Object *obj;
|
||||||
const char *base;
|
const char *base;
|
||||||
|
@ -2665,7 +2678,7 @@ _shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id)
|
||||||
|
|
||||||
if (high > si->count)
|
if (high > si->count)
|
||||||
{
|
{
|
||||||
if (eina_file_refresh(si->f))
|
if ((!safe) && eina_file_refresh(si->f))
|
||||||
{
|
{
|
||||||
WRN("Refreshing indexes.");
|
WRN("Refreshing indexes.");
|
||||||
_string_index_refresh();
|
_string_index_refresh();
|
||||||
|
@ -2717,7 +2730,7 @@ static const File_Data *
|
||||||
_shared_file_data_get_by_id(unsigned int id)
|
_shared_file_data_get_by_id(unsigned int id)
|
||||||
{
|
{
|
||||||
return (const File_Data *)
|
return (const File_Data *)
|
||||||
_shared_index_item_get_by_id(&_index.files, sizeof(File_Data), id);
|
_shared_index_item_get_by_id(&_index.files, sizeof(File_Data), id, EINA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
|
@ -2932,6 +2945,7 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
|
||||||
|
|
||||||
// Linear search in non-hashed entries. O(n)
|
// Linear search in non-hashed entries. O(n)
|
||||||
DBG("Looking for loaded image with file id %d", file_id);
|
DBG("Looking for loaded image with file id %d", file_id);
|
||||||
|
_string_index_refresh();
|
||||||
for (k = _index.images.last_entry_in_hash; k < _index.images.count; k++)
|
for (k = _index.images.last_entry_in_hash; k < _index.images.count; k++)
|
||||||
{
|
{
|
||||||
const char *file, *key;
|
const char *file, *key;
|
||||||
|
@ -2953,8 +2967,8 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = _shared_string_get(fd->key);
|
key = _shared_string_safe_get(fd->key);
|
||||||
file = _shared_string_get(fd->path);
|
file = _shared_string_safe_get(fd->path);
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
ERR("No filename for file %d", fd->id);
|
ERR("No filename for file %d", fd->id);
|
||||||
|
@ -2962,11 +2976,6 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The strings base pointer may change if the index grows
|
|
||||||
if ((key < _index.strings_entries.data) ||
|
|
||||||
(key > _index.strings_entries.data + _index.strings_entries.size))
|
|
||||||
key = _shared_string_get(fd->key);
|
|
||||||
|
|
||||||
keylen = key ? strlen(key) : 0;
|
keylen = key ? strlen(key) : 0;
|
||||||
filelen = strlen(file);
|
filelen = strlen(file);
|
||||||
|
|
||||||
|
@ -2996,7 +3005,7 @@ found:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
shmpath = _shared_string_get(idata->shm_id);
|
shmpath = _shared_string_safe_get(idata->shm_id);
|
||||||
if (!shmpath)
|
if (!shmpath)
|
||||||
{
|
{
|
||||||
ERR("Found image but it is not loaded yet: %d (doload %d)",
|
ERR("Found image but it is not loaded yet: %d (doload %d)",
|
||||||
|
@ -3012,7 +3021,7 @@ static const Font_Data *
|
||||||
_shared_font_entry_data_get_by_id(int id)
|
_shared_font_entry_data_get_by_id(int id)
|
||||||
{
|
{
|
||||||
return (Font_Data *)
|
return (Font_Data *)
|
||||||
_shared_index_item_get_by_id(&_index.fonts, sizeof(Font_Data), id);
|
_shared_index_item_get_by_id(&_index.fonts, sizeof(Font_Data), id, EINA_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Font_Data *
|
static const Font_Data *
|
||||||
|
@ -3051,8 +3060,8 @@ _shared_font_entry_data_find(Font_Entry *fe)
|
||||||
if (!cur->id) return NULL;
|
if (!cur->id) return NULL;
|
||||||
if (!cur->refcount) continue;
|
if (!cur->refcount) continue;
|
||||||
|
|
||||||
name = _shared_string_get(cur->name);
|
name = _shared_string_safe_get(cur->name);
|
||||||
source = _shared_string_get(cur->file);
|
source = _shared_string_safe_get(cur->file);
|
||||||
snprintf(hkey, PATH_MAX, "%s:%s/%u:%u:%u", source, name,
|
snprintf(hkey, PATH_MAX, "%s:%s/%u:%u:%u", source, name,
|
||||||
cur->size, cur->dpi, cur->rend_flags);
|
cur->size, cur->dpi, cur->rend_flags);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue