diff options
author | Haru <haru@dotalux.com> | 2014-07-19 20:23:35 +0200 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2014-07-19 20:27:58 +0200 |
commit | e474973e0a9f057fff212d4f6ba445d189993764 (patch) | |
tree | a62c91466e1c8ebce1f57ef7b36fc715ff345a79 /src | |
parent | f62ce0c0bae2c1b674aca5c1d7918ec97d9a7a74 (diff) | |
download | hercules-e474973e0a9f057fff212d4f6ba445d189993764.tar.gz hercules-e474973e0a9f057fff212d4f6ba445d189993764.tar.bz2 hercules-e474973e0a9f057fff212d4f6ba445d189993764.tar.xz hercules-e474973e0a9f057fff212d4f6ba445d189993764.zip |
Corrected a dangling pointer in various DBMap/DBIterator functions
- If the DBMap has the DB_RELEASE_DATA option set and it contains a
pointer, the optional returned out_data will now have its pointer
value set to NULL.
- Credits to Ind for discovering the issue.
Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/common/db.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/src/common/db.c b/src/common/db.c index cf22d8245..f414ca04d 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -1155,7 +1155,10 @@ static void db_release_data(DBKey key, DBData data, DBRelease which) { (void)key;//not used DB_COUNTSTAT(db_release_data); - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /** @@ -1174,7 +1177,10 @@ static void db_release_both(DBKey key, DBData data, DBRelease which) { DB_COUNTSTAT(db_release_both); if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /*****************************************************************************\ @@ -1428,7 +1434,7 @@ bool dbit_obj_exists(DBIterator* self) * Removes the current entry from the database. * NOTE: {@link DBIterator#exists} will return false until another entry * is fetched - * Puts data of the removed entry in out_data, if out_data is not NULL. + * Puts data of the removed entry in out_data, if out_data is not NULL (unless data has been released) * @param self Iterator * @param out_data Data of the removed entry. * @return 1 if entry was removed, 0 otherwise @@ -1449,10 +1455,10 @@ int dbit_obj_remove(DBIterator* self, DBData *out_data) DBMap_impl* db = it->db; if( db->cache == node ) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if( out_data ) memcpy(out_data, &node->data, sizeof(DBData)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[it->ht_index]); } return retval; @@ -1840,7 +1846,7 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) /** * Put the data identified by the key in the database. - * Puts the previous data in out_data, if out_data is not NULL. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) * NOTE: Uses the new key, the old one is released. * @param self Interface of the database * @param key Key that identifies the data @@ -1893,9 +1899,9 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) if (node->deleted) { db_free_remove(db, node); } else { + db->release(node->key, node->data, DB_RELEASE_BOTH); if (out_data) memcpy(out_data, &node->data, sizeof(*out_data)); - db->release(node->key, node->data, DB_RELEASE_BOTH); retval = 1; } break; @@ -1948,7 +1954,7 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) /** * Remove an entry from the database. - * Puts the previous data in out_data, if out_data is not NULL. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode*,DBNode **)}. * @param self Interface of the database * @param key Key that identifies the entry @@ -1986,10 +1992,10 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) if (!(node->deleted)) { if (db->cache == node) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if (out_data) memcpy(out_data, &node->data, sizeof(*out_data)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[hash]); } break; |