diff --git a/src/conf.c b/src/conf.c index b65e1acc320..31d72dc75d4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -261,7 +261,6 @@ int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field, { WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index"); (void)qual; - (void)cmp; if (!db || !hash || !cmp || field >= db->num_fields || field < 0) { WOLFSSL_MSG("Bad parameter"); @@ -269,6 +268,7 @@ int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field, } db->hash_fn[field] = hash; + db->cmp_fn[field] = cmp; return WOLFSSL_SUCCESS; } @@ -276,15 +276,19 @@ int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field, WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx, WOLFSSL_STRING *value) { + WOLF_STACK_OF(WOLFSSL_STRING)* data; + WOLFSSL_STRING* row = NULL; + unsigned long hash; + WOLFSSL_ENTER("wolfSSL_TXT_DB_get_by_index"); - if (!db || !db->data || idx < 0 || idx >= db->num_fields) { + if (!db || !db->data || !value || idx < 0 || idx >= db->num_fields) { WOLFSSL_MSG("Bad parameter"); return NULL; } - if (!db->hash_fn[idx]) { - WOLFSSL_MSG("Missing hash functions"); + if (!db->hash_fn[idx] || !db->cmp_fn[idx]) { + WOLFSSL_MSG("Missing hash or compare functions"); return NULL; } @@ -292,7 +296,7 @@ WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx, * then assume others do too */ if (db->data->hash_fn != db->hash_fn[idx]) { /* Set the hash and comp functions */ - WOLF_STACK_OF(WOLFSSL_STRING)* data = db->data; + data = db->data; while (data) { if (data->hash_fn != db->hash_fn[idx]) { data->hash_fn = db->hash_fn[idx]; @@ -301,7 +305,22 @@ WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx, data= data->next; } } - return (WOLFSSL_STRING*) wolfSSL_lh_retrieve(db->data, value); + + hash = db->hash_fn[idx](value); + for (data = db->data; data != NULL; data = data->next) { + row = (WOLFSSL_STRING*)wolfssl_sk_node_get_data(data, 0); + if (row != NULL) { + if (data->hash == 0) { + data->hash = db->hash_fn[idx](row); + } + if ((data->hash == hash) && (db->cmp_fn[idx](row, value) == 0)) { + break; + } + } + row = NULL; + } + + return row; } #endif /* OPENSSL_ALL && !NO_BIO */ diff --git a/tests/api.c b/tests/api.c index bab9ba8e71f..f4715b0b82d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -26658,6 +26658,13 @@ static int TXT_DB_cmp(const WOLFSSL_STRING *a, const WOLFSSL_STRING *b) { return XSTRCMP(a[3], b[3]); } + +/* Every row collides, so only TXT_DB_cmp can tell rows apart */ +static word32 TXT_DB_hash_const(const WOLFSSL_STRING *s) +{ + (void)s; + return 1; +} #endif static int test_wolfSSL_TXT_DB(void) @@ -26666,6 +26673,7 @@ static int test_wolfSSL_TXT_DB(void) #if !defined(NO_FILESYSTEM) && !defined(NO_BIO) BIO *bio = NULL; TXT_DB *db = NULL; + WOLFSSL_STRING *row = NULL; const int columns = 6; const char *fields[6] = { "V", @@ -26710,6 +26718,18 @@ static int test_wolfSSL_TXT_DB(void) fields[3] = ""; ExpectNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); + /* Colliding hashes: the row returned must be the one cmp matches */ + ExpectIntEQ(TXT_DB_create_index(db, 3, NULL, + (wolf_sk_hash_cb)(wc_ptr_t)TXT_DB_hash_const, + (wolf_lh_compare_cb)TXT_DB_cmp), 1); + fields[3] = "12DA"; + ExpectNotNull(row = TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); + if (row != NULL) { + ExpectStrEQ(row[3], "12DA"); + } + fields[3] = "FFFF"; + ExpectNull(TXT_DB_get_by_index(db, 3, (WOLFSSL_STRING*)fields)); + TXT_DB_free(db); #endif return EXPECT_RESULT(); diff --git a/wolfssl/openssl/txt_db.h b/wolfssl/openssl/txt_db.h index 889174afe0d..cdd0128f1d5 100644 --- a/wolfssl/openssl/txt_db.h +++ b/wolfssl/openssl/txt_db.h @@ -26,6 +26,9 @@ #define WOLFSSL_TXT_DB_MAX_FIELDS 10 +typedef int (*wolf_lh_compare_cb)(const void* a, + const void* b); + struct WOLFSSL_TXT_DB { int num_fields; WOLF_STACK_OF(WOLFSSL_STRING) *data; @@ -33,11 +36,10 @@ struct WOLFSSL_TXT_DB { long arg1; long arg2; wolf_sk_hash_cb hash_fn[WOLFSSL_TXT_DB_MAX_FIELDS]; + wolf_lh_compare_cb cmp_fn[WOLFSSL_TXT_DB_MAX_FIELDS]; }; typedef struct WOLFSSL_TXT_DB WOLFSSL_TXT_DB; -typedef int (*wolf_lh_compare_cb)(const void* a, - const void* b); WOLFSSL_API WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num); WOLFSSL_API long wolfSSL_TXT_DB_write(WOLFSSL_BIO *out, WOLFSSL_TXT_DB *db);