girepository: avoid crash when querying nonexistent info

It appears that cmph library can return (n+1) when querying item not
present in its original n-item-sized set.  Adjust code so that it
detects this condition and do not chase stray pointers resulting from
this bogus(?) hash result.

https://bugzilla.gnome.org/show_bug.cgi?id=675939
This commit is contained in:
Pavel Holejsovsky 2012-05-12 07:44:57 +02:00
parent 0a96da9284
commit 8af8aaa4a8
4 changed files with 17 additions and 9 deletions

View File

@ -1183,7 +1183,7 @@ void _gi_typelib_hash_builder_pack (GITypelibHashBuilder *builder, guint8* mem,
void _gi_typelib_hash_builder_destroy (GITypelibHashBuilder *builder);
guint16 _gi_typelib_hash_search (guint8* memory, const char *str);
guint16 _gi_typelib_hash_search (guint8* memory, const char *str, guint n_entries);
G_END_DECLS

View File

@ -165,15 +165,15 @@ g_typelib_get_dir_entry_by_name (GITypelib *typelib,
const char *name)
{
Section *dirindex;
gint i;
gint i, n_entries;
const char *entry_name;
DirEntry *entry;
dirindex = get_section_by_id (typelib, GI_SECTION_DIRECTORY_INDEX);
n_entries = ((Header *)typelib->data)->n_local_entries;
if (dirindex == NULL)
{
gint n_entries = ((Header *)typelib->data)->n_local_entries;
for (i = 1; i <= n_entries; i++)
{
entry = g_typelib_get_dir_entry (typelib, i);
@ -188,7 +188,7 @@ g_typelib_get_dir_entry_by_name (GITypelib *typelib,
guint8 *hash = (guint8*) &typelib->data[dirindex->offset];
guint16 index;
index = _gi_typelib_hash_search (hash, name);
index = _gi_typelib_hash_search (hash, name, n_entries);
entry = g_typelib_get_dir_entry (typelib, index + 1);
entry_name = g_typelib_get_string (typelib, entry->name);
if (strcmp (name, entry_name) == 0)

View File

@ -47,10 +47,10 @@ test_build_retrieve (void)
_gi_typelib_hash_builder_destroy (builder);
g_assert (_gi_typelib_hash_search (buf, "Action") == 0);
g_assert (_gi_typelib_hash_search (buf, "ZLibDecompressor") == 42);
g_assert (_gi_typelib_hash_search (buf, "VolumeMonitor") == 9);
g_assert (_gi_typelib_hash_search (buf, "FileMonitorFlags") == 31);
g_assert (_gi_typelib_hash_search (buf, "Action", 4) == 0);
g_assert (_gi_typelib_hash_search (buf, "ZLibDecompressor", 4) == 42);
g_assert (_gi_typelib_hash_search (buf, "VolumeMonitor", 4) == 9);
g_assert (_gi_typelib_hash_search (buf, "FileMonitorFlags", 4) == 31);
}
int

View File

@ -191,7 +191,7 @@ _gi_typelib_hash_builder_destroy (GITypelibHashBuilder *builder)
}
guint16
_gi_typelib_hash_search (guint8* memory, const char *str)
_gi_typelib_hash_search (guint8* memory, const char *str, guint n_entries)
{
guint32 *mph;
guint16 *table;
@ -203,6 +203,14 @@ _gi_typelib_hash_search (guint8* memory, const char *str)
offset = cmph_search_packed (mph, str, strlen (str));
/* Make sure that offset always lies in the entries array. cmph
cometimes generates offset larger than number of entries (for
'str' argument which is not in the hashed list). In this case,
fake the correct result and depend on caller's final check that
the entry is really the one that the caller wanted. */
if (offset >= n_entries)
offset = 0;
dirmap_offset = *((guint32*)memory);
table = (guint16*) (memory + dirmap_offset);