From: Michael M Slusarz Date: Wed, 13 Mar 2024 00:20:24 +0000 (-0600) Subject: fts-flatcurve: Fix potential crash when searching virtual mailboxes X-Git-Tag: 2.4.1~172 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2e6ff208cb6d91b9e89e82069bddbc08b76bed3;p=thirdparty%2Fdovecot%2Fcore.git fts-flatcurve: Fix potential crash when searching virtual mailboxes Fixes: Panic: file fts-search.c: line 87 (level_scores_add_vuids): assertion failed: (array_count(&vuids_arr) == array_count(&br->scores)) --- diff --git a/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc b/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc index fb90237d10..aa69bc767f 100644 --- a/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc +++ b/src/plugins/fts-flatcurve/fts-backend-flatcurve-xapian.cc @@ -212,8 +212,9 @@ struct fts_flatcurve_xapian_query_iter { Xapian::Database *db; Xapian::Enquire *enquire; Xapian::MSetIterator mset_iter; - int curr_query; - bool next_query:1; + Xapian::MSet m; + bool init:1; + bool main_query:1; }; static int @@ -2175,8 +2176,8 @@ fts_flatcurve_xapian_query_iter_init(struct flatcurve_fts_query *query) { struct fts_flatcurve_xapian_query_iter *iter; iter = new fts_flatcurve_xapian_query_iter(); - iter->curr_query = -1; - iter->next_query = TRUE; + iter->init = FALSE; + iter->main_query = TRUE; iter->query = query; iter->result = p_new(query->pool, struct fts_flatcurve_xapian_query_result, 1); @@ -2193,26 +2194,30 @@ fts_flatcurve_xapian_query_iter_next(struct fts_flatcurve_xapian_query_iter *ite if (iter->error != NULL) return FALSE; - Xapian::MSet m; - Xapian::Query *q = NULL; - if (iter->next_query) { - iter->next_query = FALSE; + if (!iter->init) { + iter->init = TRUE; - if (iter->curr_query == -1) { + Xapian::Query *q = NULL, maybe; + if (iter->main_query) { if (iter->query->xapian->query == NULL) - ++iter->curr_query; + iter->main_query = FALSE; else q = iter->query->xapian->query; } /* Maybe queries. */ - if ((iter->curr_query >= 0) && - (array_not_empty(&iter->query->xapian->maybe_queries)) && - (array_count(&iter->query->xapian->maybe_queries) > iter->curr_query)) { + if (!iter->main_query && + array_not_empty(&iter->query->xapian->maybe_queries)) { const struct flatcurve_fts_query_xapian_maybe *mquery; - mquery = array_idx(&iter->query->xapian->maybe_queries, - iter->curr_query); - q = mquery->query; + maybe = Xapian::Query(); + array_foreach(&iter->query->xapian->maybe_queries, mquery) + maybe = Xapian::Query(Xapian::Query::OP_OR, maybe, + *mquery->query); + /* Add main query to merge Xapian scores correctly. */ + if (iter->query->xapian->query != NULL) + maybe = Xapian::Query(Xapian::Query::OP_AND_MAYBE, maybe, + *iter->query->xapian->query); + q = &maybe; } if (q == NULL) @@ -2235,7 +2240,7 @@ fts_flatcurve_xapian_query_iter_next(struct fts_flatcurve_xapian_query_iter *ite iter->enquire->set_query(*q); try { - m = iter->enquire->get_mset(0, iter->db->get_doccount()); + iter->m = iter->enquire->get_mset(0, iter->db->get_doccount()); } catch (Xapian::DatabaseModifiedError &e) { /* Per documentation, this is only thrown if more than * one change has been made to the database. To @@ -2249,16 +2254,17 @@ fts_flatcurve_xapian_query_iter_next(struct fts_flatcurve_xapian_query_iter *ite i_unreached(); } - iter->mset_iter = m.begin(); + iter->mset_iter = iter->m.begin(); } - if (iter->mset_iter == m.end()) { - ++iter->curr_query; - iter->next_query = TRUE; + if (iter->mset_iter == iter->m.end()) { + if (!iter->main_query) + return FALSE; + iter->init = iter->main_query = FALSE; return fts_flatcurve_xapian_query_iter_next(iter, result_r); } - iter->result->maybe = (iter->curr_query >= 0); + iter->result->maybe = !iter->main_query; iter->result->score = iter->mset_iter.get_weight(); /* MSet docid can be an "interleaved" docid generated by * Xapian::Database when handling multiple DBs at once. Instead, we @@ -2304,13 +2310,18 @@ int fts_flatcurve_xapian_run_query(struct flatcurve_fts_query *query, iter = fts_flatcurve_xapian_query_iter_init(query); while (fts_flatcurve_xapian_query_iter_next(iter, &result)) { - if (result->maybe || query->xapian->maybe) + bool add_score = TRUE; + if (result->maybe || query->xapian->maybe) { + add_score = !seq_range_exists(&r->uids, result->uid) && + !seq_range_exists(&r->maybe_uids, result->uid); seq_range_array_add(&r->maybe_uids, result->uid); - else + } else seq_range_array_add(&r->uids, result->uid); - score = array_append_space(&r->scores); - score->score = (float)result->score; - score->uid = result->uid; + if (add_score) { + score = array_append_space(&r->scores); + score->score = (float)result->score; + score->uid = result->uid; + } } return fts_flatcurve_xapian_query_iter_deinit(&iter, error_r); }