From 41b4b6581ca4585f3b78bb4f91ac5ea20bcbedf0 Mon Sep 17 00:00:00 2001 From: Tomasz Lewandowski Date: Fri, 2 Dec 2016 03:46:14 -0800 Subject: [PATCH] Fix crash in KISSDB_IteratorNext caused by problem with handling deleted items. [IHU-12393] Change-Id: I0b072d5d0cec636102823390de9ef1ccef7b24e5 Signed-off-by: Tomasz Lewandowski --- src/key-value-store/database/kissdb.c | 24 +++++++++++++++++------- src/key-value-store/database/kissdb.h | 15 +++++++++++++++ src/key-value-store/pers_low_level_db_access.c | 21 ++++++++++++++------- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/key-value-store/database/kissdb.c b/src/key-value-store/database/kissdb.c index 7c0695d..70feeef 100644 --- a/src/key-value-store/database/kissdb.c +++ b/src/key-value-store/database/kissdb.c @@ -1310,6 +1310,7 @@ int KISSDB_Iterator_next(KISSDB_Iterator* dbi, void* kbuf, void* vbuf) { DataBlock_s* block; Hashtable_slot_s* ht; + int retVal = KISSDB_ITERATOR_NEXT_ITEM_NOT_FOUND; int64_t offset; if(dbi->db->htMappedSize < dbi->db->shared->htShmSize) @@ -1347,7 +1348,7 @@ int KISSDB_Iterator_next(KISSDB_Iterator* dbi, void* kbuf, void* vbuf) dbi->h_idx = 0; if (++dbi->h_no >= (dbi->db->shared->htNum)) { - return 0; + return KISSDB_ITERATOR_NEXT_ITEM_NOT_FOUND;//0 } else { @@ -1369,20 +1370,29 @@ int KISSDB_Iterator_next(KISSDB_Iterator* dbi, void* kbuf, void* vbuf) return KISSDB_ERROR_IO; } - block = (DataBlock_s*) (dbi->db->mappedDb + offset); - memcpy(kbuf,block->key, dbi->db->keySize); - if (vbuf != NULL) + retVal = KISSDB_ITERATOR_NEXT_ITEM_FOUND; + if (offset >= 0) + { + block = (DataBlock_s*) (dbi->db->mappedDb + offset); + memcpy(kbuf,block->key, dbi->db->keySize); + + if (vbuf != NULL) + { + memcpy(vbuf, block->value, dbi->db->valSize); + } + } + else { - memcpy(vbuf, block->value, dbi->db->valSize); + retVal = KISSDB_ITERATOR_DELETED_ITEM; } if (++dbi->h_idx >= dbi->db->htSize) { dbi->h_idx = 0; ++dbi->h_no; } - return 1; + return retVal;//1 } - return 0; + return KISSDB_ITERATOR_NEXT_ITEM_NOT_FOUND;//0 } diff --git a/src/key-value-store/database/kissdb.h b/src/key-value-store/database/kissdb.h index 582e786..949f468 100644 --- a/src/key-value-store/database/kissdb.h +++ b/src/key-value-store/database/kissdb.h @@ -171,6 +171,20 @@ typedef struct { int fd; //local fd } KISSDB; +/** + * Next item not found + */ +#define KISSDB_ITERATOR_NEXT_ITEM_NOT_FOUND 0 + +/** + * Next item found + */ +#define KISSDB_ITERATOR_NEXT_ITEM_FOUND 1 + +/** + * deleted or invalidated data found + */ +#define KISSDB_ITERATOR_DELETED_ITEM 2 /** * I/O error or file not found @@ -231,6 +245,7 @@ typedef struct { * buffer where data should be returned is too small */ #define KISSDB_ERROR_WRONG_BUFSIZE -13 + /** * Open mode: read only diff --git a/src/key-value-store/pers_low_level_db_access.c b/src/key-value-store/pers_low_level_db_access.c index 562c138..3984598 100644 --- a/src/key-value-store/pers_low_level_db_access.c +++ b/src/key-value-store/pers_low_level_db_access.c @@ -2172,6 +2172,7 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe qnobj_t obj; sint_t availableSize = size; void* pt; + int iter_ret_val; int keylength = (purpose == PersLldbPurpose_RCT) ? PERS_RCT_MAX_LENGTH_RESOURCE_ID : PERS_DB_MAX_LENGTH_KEY_NAME; char kbuf[PERS_DB_MAX_LENGTH_KEY_NAME]; @@ -2219,10 +2220,13 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe //look for keys in database file //Initialise database iterator KISSDB_Iterator_init(db, &dbi); - //get number of keys, stored in database file - while (KISSDB_Iterator_next(&dbi, &kbuf, NULL) > 0) + //get number of keys, stored in database file + while ( (iter_ret_val = KISSDB_Iterator_next(&dbi, &kbuf, NULL)) > 0) { - keyCountFile++; + if (iter_ret_val == KISSDB_ITERATOR_NEXT_ITEM_FOUND) + { + keyCountFile++; + } } if ((keyCountCache + keyCountFile) > 0) @@ -2254,12 +2258,15 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe //put keys in database file to hashtable (existing key gets overwritten -> no duplicate keys) KISSDB_Iterator_init(db, &dbi); memset(kbuf, 0, keylength); - while (KISSDB_Iterator_next(&dbi, &kbuf, NULL) > 0) + while ( (iter_ret_val = KISSDB_Iterator_next(&dbi, &kbuf, NULL)) > 0) { - size_t keyLen = strnlen(kbuf, sizeof(kbuf)); - if (keyLen > 0) + if (iter_ret_val == KISSDB_ITERATOR_NEXT_ITEM_FOUND) { - tbl->put(tbl, kbuf, "0", 1); + size_t keyLen = strnlen(kbuf, sizeof(kbuf)); + if (keyLen > 0) + { + tbl->put(tbl, kbuf, "0", 1); + } } } -- 2.5.0