Compare commits
No commits in common. "c8" and "imports/c8-beta/dovecot-2.3.16-3.el8" have entirely different histories.
c8
...
imports/c8
@ -1,17 +0,0 @@
|
|||||||
diff --git a/src/lib-index/mail-index-sync.c b/src/lib-index/mail-index-sync.c
|
|
||||||
index 6322ee1869..c847f1cc01 100644
|
|
||||||
--- a/src/lib-index/mail-index-sync.c
|
|
||||||
+++ b/src/lib-index/mail-index-sync.c
|
|
||||||
@@ -544,6 +544,12 @@ static bool mail_index_sync_view_have_any(struct mail_index_view *view,
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
mail_transaction_log_get_head(view->index->log, &log_seq, &log_offset);
|
|
||||||
+ if (log_seq < view->map->hdr.log_file_seq ||
|
|
||||||
+ ((log_seq == view->map->hdr.log_file_seq &&
|
|
||||||
+ log_offset < view->map->hdr.log_file_tail_offset))) {
|
|
||||||
+ /* invalid offsets - let the syncing handle the error */
|
|
||||||
+ return TRUE;
|
|
||||||
+ }
|
|
||||||
if (mail_transaction_log_view_set(view->log_view,
|
|
||||||
view->map->hdr.log_file_seq,
|
|
||||||
view->map->hdr.log_file_tail_offset,
|
|
@ -1,578 +0,0 @@
|
|||||||
From 9f3002393fe1c1fe317121d03591569dac120739 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Tue, 17 Aug 2021 19:09:13 +0200
|
|
||||||
Subject: [PATCH 01/12] lib-sieve: sieve-interpreter - Fix field mixup in debug
|
|
||||||
message.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-interpreter.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
|
|
||||||
index 9ee6c659..274e142d 100644
|
|
||||||
--- a/src/lib-sieve/sieve-interpreter.c
|
|
||||||
+++ b/src/lib-sieve/sieve-interpreter.c
|
|
||||||
@@ -1003,8 +1003,8 @@ int sieve_interpreter_continue(struct sieve_interpreter *interp,
|
|
||||||
}
|
|
||||||
e_debug(e->event(), "Finished running script `%s' "
|
|
||||||
"(status=%s, resource usage: %s)",
|
|
||||||
- sieve_execution_exitcode_to_str(ret),
|
|
||||||
sieve_binary_source(interp->runenv.sbin),
|
|
||||||
+ sieve_execution_exitcode_to_str(ret),
|
|
||||||
sieve_resource_usage_get_summary(&interp->rusage));
|
|
||||||
interp->running = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
From 54e020c1212f626049bffc6c6fea8e606a893af2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 01:44:23 +0200
|
|
||||||
Subject: [PATCH 02/12] lib-sieve: sieve-result - Remove success parameter from
|
|
||||||
sieve_result_implicit_keep_execute().
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 18 ++++++++----------
|
|
||||||
1 file changed, 8 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 55eb9f54..d3f2f925 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1475,8 +1475,7 @@ void sieve_result_execution_destroy(struct sieve_result_execution **_rexec)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
-sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
|
|
||||||
- bool success)
|
|
||||||
+sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
|
|
||||||
{
|
|
||||||
const struct sieve_action_exec_env *aenv = &rexec->action_env;
|
|
||||||
struct sieve_result *result = aenv->result;
|
|
||||||
@@ -1486,6 +1485,7 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
|
|
||||||
struct sieve_action_execution *aexec_keep = &rexec->keep;
|
|
||||||
struct sieve_result_action *ract_keep = &rexec->keep_action;
|
|
||||||
struct sieve_action *act_keep = &ract_keep->action;
|
|
||||||
+ bool success = (rexec->status == SIEVE_EXEC_OK);
|
|
||||||
|
|
||||||
if (rexec->keep_equiv_action != NULL) {
|
|
||||||
e_debug(rexec->event, "No implicit keep needed "
|
|
||||||
@@ -1579,8 +1579,8 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- e_debug(rexec->event, "Execute implicit keep (failure=%s)",
|
|
||||||
- (!success ? "yes" : "no"));
|
|
||||||
+ e_debug(rexec->event, "Execute implicit keep (status=%s)",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
|
|
||||||
/* Initialize side effects */
|
|
||||||
sieve_action_execution_add_side_effects(rexec, aexec_keep, ract_keep);
|
|
||||||
@@ -1633,7 +1633,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
|
|
||||||
/* Start keep if necessary */
|
|
||||||
if (act_keep->def == NULL ||
|
|
||||||
aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
|
|
||||||
- sieve_result_implicit_keep_execute(rexec, success);
|
|
||||||
+ sieve_result_implicit_keep_execute(rexec);
|
|
||||||
/* Switch to failure keep if necessary. */
|
|
||||||
} else if (rexec->keep_success && !success){
|
|
||||||
e_debug(rexec->event, "Switch to failure implicit keep");
|
|
||||||
@@ -1645,7 +1645,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
|
|
||||||
i_zero(aexec_keep);
|
|
||||||
|
|
||||||
/* Start failure keep action. */
|
|
||||||
- sieve_result_implicit_keep_execute(rexec, success);
|
|
||||||
+ sieve_result_implicit_keep_execute(rexec);
|
|
||||||
}
|
|
||||||
if (act_keep->def == NULL)
|
|
||||||
return rexec->keep_status;
|
|
||||||
@@ -1931,10 +1931,8 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
|
|
||||||
/* Execute implicit keep if the transaction failed or when the
|
|
||||||
implicit keep was not canceled during transaction.
|
|
||||||
*/
|
|
||||||
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
|
|
||||||
- sieve_result_implicit_keep_execute(
|
|
||||||
- rexec, (rexec->status == SIEVE_EXEC_OK));
|
|
||||||
- }
|
|
||||||
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
|
|
||||||
+ sieve_result_implicit_keep_execute(rexec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transaction commit/rollback */
|
|
||||||
|
|
||||||
From 291f2fdb77b86db566dca7c028dd93fc741f6b31 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 01:40:57 +0200
|
|
||||||
Subject: [PATCH 03/12] lib-sieve: sieve-result - Remove success parameter from
|
|
||||||
sieve_result_implicit_keep_finalize().
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 11 +++++------
|
|
||||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index d3f2f925..3cf2c02a 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1603,8 +1603,7 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
-sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
|
|
||||||
- bool success)
|
|
||||||
+sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
{
|
|
||||||
const struct sieve_action_exec_env *aenv = &rexec->action_env;
|
|
||||||
const struct sieve_execute_env *eenv = aenv->exec_env;
|
|
||||||
@@ -1612,6 +1611,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
|
|
||||||
struct sieve_result_action *ract_keep = &rexec->keep_action;
|
|
||||||
struct sieve_action *act_keep = &ract_keep->action;
|
|
||||||
int commit_status = SIEVE_EXEC_OK;
|
|
||||||
+ bool success = (rexec->status == SIEVE_EXEC_OK);
|
|
||||||
|
|
||||||
if (rexec->keep_equiv_action != NULL) {
|
|
||||||
struct sieve_action_execution *ke_aexec =
|
|
||||||
@@ -1627,8 +1627,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec,
|
|
||||||
return rexec->keep_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
- e_debug(rexec->event, "Finalize implicit keep (failure=%s)",
|
|
||||||
- (!success ? "yes" : "no"));
|
|
||||||
+ e_debug(rexec->event, "Finalize implicit keep (status=%s)",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
|
|
||||||
/* Start keep if necessary */
|
|
||||||
if (act_keep->def == NULL ||
|
|
||||||
@@ -1950,8 +1950,7 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
|
|
||||||
implicit keep was not canceled during transaction.
|
|
||||||
*/
|
|
||||||
if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
|
|
||||||
- ret = sieve_result_implicit_keep_finalize(
|
|
||||||
- rexec, (rexec->status == SIEVE_EXEC_OK));
|
|
||||||
+ ret = sieve_result_implicit_keep_finalize(rexec);
|
|
||||||
switch (ret) {
|
|
||||||
case SIEVE_EXEC_OK:
|
|
||||||
if (result_status == SIEVE_EXEC_TEMP_FAILURE)
|
|
||||||
|
|
||||||
From 10e347e3c9eb5e7bf5bc6f178389005357f527fe Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:07:01 +0200
|
|
||||||
Subject: [PATCH 04/12] lib-sieve: sieve-result - Move temp failure status
|
|
||||||
checks into sieve_result_implicit_keep_execute().
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 38 ++++++++++++++++++++++++------------
|
|
||||||
1 file changed, 26 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 3cf2c02a..44afeef7 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -934,6 +934,7 @@ struct sieve_result_execution {
|
|
||||||
bool keep_success:1;
|
|
||||||
bool keep_explicit:1;
|
|
||||||
bool keep_implicit:1;
|
|
||||||
+ bool keep_finalizing:1;
|
|
||||||
bool seen_delivery:1;
|
|
||||||
bool executed:1;
|
|
||||||
bool executed_delivery:1;
|
|
||||||
@@ -1485,7 +1486,24 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
|
|
||||||
struct sieve_action_execution *aexec_keep = &rexec->keep;
|
|
||||||
struct sieve_result_action *ract_keep = &rexec->keep_action;
|
|
||||||
struct sieve_action *act_keep = &ract_keep->action;
|
|
||||||
- bool success = (rexec->status == SIEVE_EXEC_OK);
|
|
||||||
+ bool success = FALSE;
|
|
||||||
+
|
|
||||||
+ switch (rexec->status) {
|
|
||||||
+ case SIEVE_EXEC_OK:
|
|
||||||
+ success = TRUE;
|
|
||||||
+ break;
|
|
||||||
+ case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
+ case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
+ if (rexec->executed)
|
|
||||||
+ break;
|
|
||||||
+ if (rexec->committed)
|
|
||||||
+ break;
|
|
||||||
+ if (rexec->keep_finalizing)
|
|
||||||
+ break;
|
|
||||||
+ return;
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (rexec->keep_equiv_action != NULL) {
|
|
||||||
e_debug(rexec->event, "No implicit keep needed "
|
|
||||||
@@ -1630,6 +1648,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
e_debug(rexec->event, "Finalize implicit keep (status=%s)",
|
|
||||||
sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
|
|
||||||
+ rexec->keep_finalizing = TRUE;
|
|
||||||
+
|
|
||||||
/* Start keep if necessary */
|
|
||||||
if (act_keep->def == NULL ||
|
|
||||||
aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
|
|
||||||
@@ -1923,17 +1943,11 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
|
|
||||||
return rexec->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Execute implicit keep if necessary */
|
|
||||||
-
|
|
||||||
- if (rexec->executed ||
|
|
||||||
- (rexec->status != SIEVE_EXEC_TEMP_FAILURE &&
|
|
||||||
- rexec->status != SIEVE_EXEC_RESOURCE_LIMIT)) {
|
|
||||||
- /* Execute implicit keep if the transaction failed or when the
|
|
||||||
- implicit keep was not canceled during transaction.
|
|
||||||
- */
|
|
||||||
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
|
|
||||||
- sieve_result_implicit_keep_execute(rexec);
|
|
||||||
- }
|
|
||||||
+ /* Execute implicit keep if the transaction failed or when the
|
|
||||||
+ implicit keep was not canceled during transaction.
|
|
||||||
+ */
|
|
||||||
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
|
|
||||||
+ sieve_result_implicit_keep_execute(rexec);
|
|
||||||
|
|
||||||
/* Transaction commit/rollback */
|
|
||||||
|
|
||||||
|
|
||||||
From c84e6e5d8d1d8b03a0ba5958804d200c6e1916d8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:26:32 +0200
|
|
||||||
Subject: [PATCH 05/12] lib-sieve: sieve-result - Move temp failure status
|
|
||||||
checks into sieve_result_implicit_keep_finalize().
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 56 +++++++++++++++++++++---------------
|
|
||||||
1 file changed, 33 insertions(+), 23 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 44afeef7..10cc3b95 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1629,7 +1629,20 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
struct sieve_result_action *ract_keep = &rexec->keep_action;
|
|
||||||
struct sieve_action *act_keep = &ract_keep->action;
|
|
||||||
int commit_status = SIEVE_EXEC_OK;
|
|
||||||
- bool success = (rexec->status == SIEVE_EXEC_OK);
|
|
||||||
+ bool success = FALSE;
|
|
||||||
+
|
|
||||||
+ switch (rexec->status) {
|
|
||||||
+ case SIEVE_EXEC_OK:
|
|
||||||
+ success = TRUE;
|
|
||||||
+ break;
|
|
||||||
+ case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
+ case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
+ if (rexec->committed)
|
|
||||||
+ break;
|
|
||||||
+ return rexec->status;
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (rexec->keep_equiv_action != NULL) {
|
|
||||||
struct sieve_action_execution *ke_aexec =
|
|
||||||
@@ -1957,32 +1970,29 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
|
|
||||||
/* Commit implicit keep if necessary */
|
|
||||||
|
|
||||||
result_status = rexec->status;
|
|
||||||
- if (rexec->committed ||
|
|
||||||
- (rexec->status != SIEVE_EXEC_TEMP_FAILURE &&
|
|
||||||
- rexec->status != SIEVE_EXEC_RESOURCE_LIMIT)) {
|
|
||||||
- /* Commit implicit keep if the transaction failed or when the
|
|
||||||
- implicit keep was not canceled during transaction.
|
|
||||||
- */
|
|
||||||
- if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
|
|
||||||
- ret = sieve_result_implicit_keep_finalize(rexec);
|
|
||||||
- switch (ret) {
|
|
||||||
- case SIEVE_EXEC_OK:
|
|
||||||
- if (result_status == SIEVE_EXEC_TEMP_FAILURE)
|
|
||||||
- result_status = SIEVE_EXEC_FAILURE;
|
|
||||||
+
|
|
||||||
+ /* Commit implicit keep if the transaction failed or when the
|
|
||||||
+ implicit keep was not canceled during transaction.
|
|
||||||
+ */
|
|
||||||
+ if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit) {
|
|
||||||
+ ret = sieve_result_implicit_keep_finalize(rexec);
|
|
||||||
+ switch (ret) {
|
|
||||||
+ case SIEVE_EXEC_OK:
|
|
||||||
+ if (result_status == SIEVE_EXEC_TEMP_FAILURE)
|
|
||||||
+ result_status = SIEVE_EXEC_FAILURE;
|
|
||||||
+ break;
|
|
||||||
+ case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
+ if (!rexec->committed) {
|
|
||||||
+ result_status = ret;
|
|
||||||
break;
|
|
||||||
- case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
- if (!rexec->committed) {
|
|
||||||
- result_status = ret;
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- /* fall through */
|
|
||||||
- default:
|
|
||||||
- result_status = SIEVE_EXEC_KEEP_FAILED;
|
|
||||||
}
|
|
||||||
+ /* fall through */
|
|
||||||
+ default:
|
|
||||||
+ result_status = SIEVE_EXEC_KEEP_FAILED;
|
|
||||||
}
|
|
||||||
- if (rexec->status == SIEVE_EXEC_OK)
|
|
||||||
- rexec->status = result_status;
|
|
||||||
}
|
|
||||||
+ if (rexec->status == SIEVE_EXEC_OK)
|
|
||||||
+ rexec->status = result_status;
|
|
||||||
|
|
||||||
/* Finish execution */
|
|
||||||
|
|
||||||
|
|
||||||
From 92b4b06d5d8deeefdd17d5fb18d7f0d23e8e414b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:46:18 +0200
|
|
||||||
Subject: [PATCH 06/12] lib-sieve: sieve-result - Skip implicit keep in
|
|
||||||
execution stage upon temp failure.
|
|
||||||
|
|
||||||
It will be executed in the commit phase if necessary; don't do it early; it will
|
|
||||||
only be rolled back.
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 2 --
|
|
||||||
1 file changed, 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 10cc3b95..82354831 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1494,8 +1494,6 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
|
|
||||||
break;
|
|
||||||
case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
- if (rexec->executed)
|
|
||||||
- break;
|
|
||||||
if (rexec->committed)
|
|
||||||
break;
|
|
||||||
if (rexec->keep_finalizing)
|
|
||||||
|
|
||||||
From f2b81cc6ebaa3001bde693f7abdb990f467f7831 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:56:32 +0200
|
|
||||||
Subject: [PATCH 07/12] lib-sieve: sieve-result - Fix handling of resource
|
|
||||||
limit status after implicit keep commit.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 82354831..96582075 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1980,6 +1980,7 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
|
|
||||||
result_status = SIEVE_EXEC_FAILURE;
|
|
||||||
break;
|
|
||||||
case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
+ case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
if (!rexec->committed) {
|
|
||||||
result_status = ret;
|
|
||||||
break;
|
|
||||||
|
|
||||||
From 293f0027106a725e4cbcf56b673f1eedda00c317 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:54:25 +0200
|
|
||||||
Subject: [PATCH 08/12] lib-sieve: sieve-result - Fix resource leak occurring
|
|
||||||
when implicit keep is executed before temporary failure at commit.
|
|
||||||
|
|
||||||
In the commit phase the implicit keep was never finalized, meaning that it was
|
|
||||||
not rolled back and thus not cleaned up properly. This leads to a memory leak
|
|
||||||
and a mailbox reference leak. This in turn causes an assert crash at the end
|
|
||||||
of delivery when the mail user is destroyed.
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 18 ++++++++++++++----
|
|
||||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 96582075..10ea349c 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1627,7 +1627,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
struct sieve_result_action *ract_keep = &rexec->keep_action;
|
|
||||||
struct sieve_action *act_keep = &ract_keep->action;
|
|
||||||
int commit_status = SIEVE_EXEC_OK;
|
|
||||||
- bool success = FALSE;
|
|
||||||
+ bool success = FALSE, temp_failure = FALSE;
|
|
||||||
|
|
||||||
switch (rexec->status) {
|
|
||||||
case SIEVE_EXEC_OK:
|
|
||||||
@@ -1637,7 +1637,15 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
if (rexec->committed)
|
|
||||||
break;
|
|
||||||
- return rexec->status;
|
|
||||||
+
|
|
||||||
+ if (aexec_keep->state !=
|
|
||||||
+ SIEVE_ACTION_EXECUTION_STATE_EXECUTED)
|
|
||||||
+ return rexec->status;
|
|
||||||
+ /* Roll back for temporary failure when no other action
|
|
||||||
+ is committed. */
|
|
||||||
+ commit_status = rexec->status;
|
|
||||||
+ temp_failure = TRUE;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -1662,8 +1670,10 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
rexec->keep_finalizing = TRUE;
|
|
||||||
|
|
||||||
/* Start keep if necessary */
|
|
||||||
- if (act_keep->def == NULL ||
|
|
||||||
- aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
|
|
||||||
+ if (temp_failure) {
|
|
||||||
+ rexec->keep_status = rexec->status;
|
|
||||||
+ } else if (act_keep->def == NULL ||
|
|
||||||
+ aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
|
|
||||||
sieve_result_implicit_keep_execute(rexec);
|
|
||||||
/* Switch to failure keep if necessary. */
|
|
||||||
} else if (rexec->keep_success && !success){
|
|
||||||
|
|
||||||
From 81bd53d6c9fa14fc6b32304e49dddb8fd022de91 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 13:29:41 +0200
|
|
||||||
Subject: [PATCH 09/12] lib-sieve: sieve-result - Assert that implicit keep is
|
|
||||||
executed in sieve_result_implicit_keep_finalize().
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 10ea349c..de97d6ae 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1691,6 +1691,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
if (act_keep->def == NULL)
|
|
||||||
return rexec->keep_status;
|
|
||||||
|
|
||||||
+ i_assert(aexec_keep->state == SIEVE_ACTION_EXECUTION_STATE_EXECUTED);
|
|
||||||
+
|
|
||||||
/* Finalize keep action */
|
|
||||||
rexec->keep_status = sieve_result_action_commit_or_rollback(
|
|
||||||
rexec, aexec_keep, rexec->keep_status, &commit_status);
|
|
||||||
|
|
||||||
From dbf5b62ba82766a7d824e81005b2517d96984ef0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 02:43:05 +0200
|
|
||||||
Subject: [PATCH 10/12] lib-sieve: sieve-result - Add debug messages for temp
|
|
||||||
failure handling.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 28 +++++++++++++++++++++++++---
|
|
||||||
1 file changed, 25 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index de97d6ae..c21c8017 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1494,10 +1494,21 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
|
|
||||||
break;
|
|
||||||
case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
- if (rexec->committed)
|
|
||||||
+ if (rexec->committed) {
|
|
||||||
+ e_debug(rexec->event,
|
|
||||||
+ "Temporary failure occurred (status=%s), "
|
|
||||||
+ "but other actions were already committed: "
|
|
||||||
+ "execute failure implicit keep",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
break;
|
|
||||||
+ }
|
|
||||||
if (rexec->keep_finalizing)
|
|
||||||
break;
|
|
||||||
+
|
|
||||||
+ e_debug(rexec->event,
|
|
||||||
+ "Skip implicit keep for temporary failure "
|
|
||||||
+ "(state=execute, status=%s)",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
@@ -1635,12 +1646,23 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
|
|
||||||
break;
|
|
||||||
case SIEVE_EXEC_TEMP_FAILURE:
|
|
||||||
case SIEVE_EXEC_RESOURCE_LIMIT:
|
|
||||||
- if (rexec->committed)
|
|
||||||
+ if (rexec->committed) {
|
|
||||||
+ e_debug(rexec->event,
|
|
||||||
+ "Temporary failure occurred (status=%s), "
|
|
||||||
+ "but other actions were already committed: "
|
|
||||||
+ "commit failure implicit keep",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (aexec_keep->state !=
|
|
||||||
- SIEVE_ACTION_EXECUTION_STATE_EXECUTED)
|
|
||||||
+ SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
|
|
||||||
+ e_debug(rexec->event,
|
|
||||||
+ "Skip implicit keep for temporary failure "
|
|
||||||
+ "(state=commit, status=%s)",
|
|
||||||
+ sieve_execution_exitcode_to_str(rexec->status));
|
|
||||||
return rexec->status;
|
|
||||||
+ }
|
|
||||||
/* Roll back for temporary failure when no other action
|
|
||||||
is committed. */
|
|
||||||
commit_status = rexec->status;
|
|
||||||
|
|
||||||
From 65d771c15bf443690580dbb0643556794106522b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 13:26:26 +0200
|
|
||||||
Subject: [PATCH 11/12] lib-sieve: sieve-result - Indicate in
|
|
||||||
sieve_result_transaction_execute() debug message whether actions were
|
|
||||||
executed.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index c21c8017..6f3cb954 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1796,10 +1796,11 @@ sieve_result_transaction_execute(struct sieve_result_execution *rexec,
|
|
||||||
}
|
|
||||||
|
|
||||||
e_debug(rexec->event, "Finished executing actions "
|
|
||||||
- "(status=%s, keep=%s)",
|
|
||||||
+ "(status=%s, keep=%s, executed=%s)",
|
|
||||||
sieve_execution_exitcode_to_str(status),
|
|
||||||
(rexec->keep_explicit ? "explicit" :
|
|
||||||
- (rexec->keep_implicit ? "implicit" : "none")));
|
|
||||||
+ (rexec->keep_implicit ? "implicit" : "none")),
|
|
||||||
+ (rexec->executed ? "yes" : "no"));
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
From 4596d39908a868783fae9a0c2fd264409c0aaa96 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stephan Bosch <stephan.bosch@open-xchange.com>
|
|
||||||
Date: Wed, 18 Aug 2021 13:27:50 +0200
|
|
||||||
Subject: [PATCH 12/12] lib-sieve: sieve-result - Indicate in
|
|
||||||
sieve_result_transaction_finalize() debug message whether actions were
|
|
||||||
committed.
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-sieve/sieve-result.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
|
|
||||||
index 6f3cb954..effd6f28 100644
|
|
||||||
--- a/src/lib-sieve/sieve-result.c
|
|
||||||
+++ b/src/lib-sieve/sieve-result.c
|
|
||||||
@@ -1859,10 +1859,11 @@ sieve_result_transaction_commit_or_rollback(
|
|
||||||
}
|
|
||||||
|
|
||||||
e_debug(rexec->event, "Finished finalizing actions "
|
|
||||||
- "(status=%s, keep=%s)",
|
|
||||||
+ "(status=%s, keep=%s, committed=%s)",
|
|
||||||
sieve_execution_exitcode_to_str(status),
|
|
||||||
(rexec->keep_explicit ? "explicit" :
|
|
||||||
- (rexec->keep_implicit ? "implicit" : "none")));
|
|
||||||
+ (rexec->keep_implicit ? "implicit" : "none")),
|
|
||||||
+ (rexec->committed ? "yes" : "no"));
|
|
||||||
|
|
||||||
return commit_status;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
From bdf4474ed82aaf964e7d94e72ca56b496e3815f9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Fri, 1 Oct 2021 15:08:45 +0300
|
|
||||||
Subject: [PATCH] virtual: Fix leaking mailboxes if virtual mailbox can't be
|
|
||||||
opened
|
|
||||||
|
|
||||||
Fixes also a crash at deinit:
|
|
||||||
Panic: file mail-user.c: line 232 (mail_user_deinit): assertion failed: ((*user)->refcount == 1)
|
|
||||||
---
|
|
||||||
src/plugins/virtual/virtual-storage.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c
|
|
||||||
index 2f31503d53..a0779cc186 100644
|
|
||||||
--- a/src/plugins/virtual/virtual-storage.c
|
|
||||||
+++ b/src/plugins/virtual/virtual-storage.c
|
|
||||||
@@ -495,12 +495,12 @@ static int virtual_mailbox_open(struct mailbox *box)
|
|
||||||
ret = virtual_mailboxes_open(mbox, box->flags);
|
|
||||||
array_pop_back(&mbox->storage->open_stack);
|
|
||||||
}
|
|
||||||
+ if (ret == 0)
|
|
||||||
+ ret = index_storage_mailbox_open(box, FALSE);
|
|
||||||
if (ret < 0) {
|
|
||||||
virtual_mailbox_close_internal(mbox);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- if (index_storage_mailbox_open(box, FALSE) < 0)
|
|
||||||
- return -1;
|
|
||||||
|
|
||||||
mbox->virtual_ext_id =
|
|
||||||
mail_index_ext_register(mbox->box.index, "virtual", 0,
|
|
@ -1,22 +0,0 @@
|
|||||||
From 9a3e0d099044d3a7478c3a24ccb8990181767f7c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Duncan Bellamy <dunk@denkimushi.com>
|
|
||||||
Date: Sat, 6 Mar 2021 14:25:29 +0000
|
|
||||||
Subject: [PATCH] imap: Shorten test-imap-client-hibernate socket path length
|
|
||||||
|
|
||||||
---
|
|
||||||
src/imap/test-imap-client-hibernate.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/imap/test-imap-client-hibernate.c b/src/imap/test-imap-client-hibernate.c
|
|
||||||
index 9b90e1bd9a..c5392fa3fc 100644
|
|
||||||
--- a/src/imap/test-imap-client-hibernate.c
|
|
||||||
+++ b/src/imap/test-imap-client-hibernate.c
|
|
||||||
@@ -19,7 +19,7 @@
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
-#define TEMP_DIRNAME ".test-imap-client-hibernate"
|
|
||||||
+#define TEMP_DIRNAME ".test-ich"
|
|
||||||
|
|
||||||
#define EVILSTR "\t\r\n\001"
|
|
||||||
|
|
@ -1,976 +0,0 @@
|
|||||||
From 8e4c42dbb3c770fcdbc396f2abcf1bc228ec548d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Fri, 9 Feb 2024 00:32:39 +0200
|
|
||||||
Subject: [PATCH 1/6] lib: test-llist - Fix dllist2 test name
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib/test-llist.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib/test-llist.c b/src/lib/test-llist.c
|
|
||||||
index d57006ce2aa..ed584318fa3 100644
|
|
||||||
--- a/src/lib/test-llist.c
|
|
||||||
+++ b/src/lib/test-llist.c
|
|
||||||
@@ -71,7 +71,7 @@ static void test_dllist2(void)
|
|
||||||
l2 = t_new(struct dllist, 1);
|
|
||||||
l1 = t_new(struct dllist, 1);
|
|
||||||
|
|
||||||
- test_begin("dllist");
|
|
||||||
+ test_begin("dllist2");
|
|
||||||
/* prepend to empty */
|
|
||||||
DLLIST2_PREPEND(&head, &tail, l3);
|
|
||||||
test_assert(head == l3 && tail == l3);
|
|
||||||
|
|
||||||
From cee08202c759a3bdf185d998dcf888ebd1bc6e36 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Fri, 9 Feb 2024 00:33:00 +0200
|
|
||||||
Subject: [PATCH 2/6] lib: Add DLLIST2_JOIN()
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib/llist.h | 14 ++++++++++++++
|
|
||||||
src/lib/test-llist.c | 39 +++++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 53 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/lib/llist.h b/src/lib/llist.h
|
|
||||||
index 8a52e873352..5ad5d75c0df 100644
|
|
||||||
--- a/src/lib/llist.h
|
|
||||||
+++ b/src/lib/llist.h
|
|
||||||
@@ -78,4 +78,18 @@
|
|
||||||
#define DLLIST2_REMOVE(head, tail, item) \
|
|
||||||
DLLIST2_REMOVE_FULL(head, tail, item, prev, next)
|
|
||||||
|
|
||||||
+#define DLLIST2_JOIN_FULL(head1, tail1, head2, tail2, prev, next) STMT_START { \
|
|
||||||
+ if (*(head1) == NULL) { \
|
|
||||||
+ *(head1) = *(head2); \
|
|
||||||
+ *(tail1) = *(tail2); \
|
|
||||||
+ } else if (*(head2) != NULL) { \
|
|
||||||
+ (*(tail1))->next = *(head2); \
|
|
||||||
+ (*(head2))->prev = *(tail1); \
|
|
||||||
+ (*tail1) = (*tail2); \
|
|
||||||
+ } \
|
|
||||||
+ } STMT_END
|
|
||||||
+
|
|
||||||
+#define DLLIST2_JOIN(head1, tail1, head2, tail2) \
|
|
||||||
+ DLLIST2_JOIN_FULL(head1, tail1, head2, tail2, prev, next)
|
|
||||||
+
|
|
||||||
#endif
|
|
||||||
diff --git a/src/lib/test-llist.c b/src/lib/test-llist.c
|
|
||||||
index ed584318fa3..e293eb6a603 100644
|
|
||||||
--- a/src/lib/test-llist.c
|
|
||||||
+++ b/src/lib/test-llist.c
|
|
||||||
@@ -131,8 +131,47 @@ static void test_dllist2(void)
|
|
||||||
test_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void test_dllist2_join(void)
|
|
||||||
+{
|
|
||||||
+ struct dllist *head, *tail, *elem[4];
|
|
||||||
+ struct dllist *head2, *tail2, *elem2[N_ELEMENTS(elem)];
|
|
||||||
+
|
|
||||||
+ test_begin("dllist2 join");
|
|
||||||
+ for (unsigned int i = 0; i < N_ELEMENTS(elem); i++) {
|
|
||||||
+ elem[i] = t_new(struct dllist, 1);
|
|
||||||
+ elem2[i] = t_new(struct dllist, 1);
|
|
||||||
+ }
|
|
||||||
+ for (unsigned int i = 0; i < N_ELEMENTS(elem); i++) {
|
|
||||||
+ for (unsigned int j = 0; j < N_ELEMENTS(elem2); j++) {
|
|
||||||
+ head = tail = head2 = tail2 = NULL;
|
|
||||||
+ for (unsigned int n = 0; n < i; n++)
|
|
||||||
+ DLLIST2_APPEND(&head, &tail, elem[n]);
|
|
||||||
+ for (unsigned int n = 0; n < j; n++)
|
|
||||||
+ DLLIST2_APPEND(&head2, &tail2, elem2[n]);
|
|
||||||
+ DLLIST2_JOIN(&head, &tail, &head2, &tail2);
|
|
||||||
+
|
|
||||||
+ /* verify */
|
|
||||||
+ struct dllist *tmp = head, *last = NULL;
|
|
||||||
+ for (unsigned int n = 0; n < i; n++) {
|
|
||||||
+ test_assert(tmp == elem[n]);
|
|
||||||
+ last = tmp;
|
|
||||||
+ tmp = tmp->next;
|
|
||||||
+ }
|
|
||||||
+ for (unsigned int n = 0; n < j; n++) {
|
|
||||||
+ test_assert(tmp == elem2[n]);
|
|
||||||
+ last = tmp;
|
|
||||||
+ tmp = tmp->next;
|
|
||||||
+ }
|
|
||||||
+ test_assert(tmp == NULL);
|
|
||||||
+ test_assert(tail == last);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void test_llist(void)
|
|
||||||
{
|
|
||||||
test_dllist();
|
|
||||||
test_dllist2();
|
|
||||||
+ test_dllist2_join();
|
|
||||||
}
|
|
||||||
|
|
||||||
From 0bae091859c905dc335f21eed01347e6b8338672 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Tue, 30 Jan 2024 22:42:50 +0200
|
|
||||||
Subject: [PATCH 3/6] lib-mail: test-imap-envelope - Use test_assert_idx()
|
|
||||||
where possible
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-imap/test-imap-envelope.c | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-imap/test-imap-envelope.c b/src/lib-imap/test-imap-envelope.c
|
|
||||||
index 1f295e58bab..c9b92b4be2b 100644
|
|
||||||
--- a/src/lib-imap/test-imap-envelope.c
|
|
||||||
+++ b/src/lib-imap/test-imap-envelope.c
|
|
||||||
@@ -157,7 +157,7 @@ static void test_imap_envelope_write(void)
|
|
||||||
envlp = msg_parse(pool, test->message);
|
|
||||||
|
|
||||||
imap_envelope_write(envlp, str);
|
|
||||||
- test_assert(strcmp(str_c(str), test->envelope) == 0);
|
|
||||||
+ test_assert_idx(strcmp(str_c(str), test->envelope) == 0, i);
|
|
||||||
|
|
||||||
pool_unref(&pool);
|
|
||||||
test_end();
|
|
||||||
@@ -179,12 +179,12 @@ static void test_imap_envelope_parse(void)
|
|
||||||
test_begin(t_strdup_printf("imap envelope parser [%u]", i));
|
|
||||||
|
|
||||||
ret = imap_envelope_parse(test->envelope, pool, &envlp, &error);
|
|
||||||
- test_assert(ret);
|
|
||||||
+ test_assert_idx(ret, i);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
str_truncate(str, 0);
|
|
||||||
imap_envelope_write(envlp, str);
|
|
||||||
- test_assert(strcmp(str_c(str), test->envelope) == 0);
|
|
||||||
+ test_assert_idx(strcmp(str_c(str), test->envelope) == 0, i);
|
|
||||||
} else {
|
|
||||||
i_error("Invalid envelope: %s", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
From a1c9b0409454e45937bf7e9c3685f5e91d6a5a43 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Sun, 4 Feb 2024 00:26:57 +0200
|
|
||||||
Subject: [PATCH 4/6] lib-mail: Change message_address to be doubly linked list
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-imap/imap-envelope.c | 11 +-
|
|
||||||
src/lib-mail/message-address.c | 8 +-
|
|
||||||
src/lib-mail/message-address.h | 2 +-
|
|
||||||
src/lib-mail/test-message-address.c | 226 ++++++++++++++--------------
|
|
||||||
4 files changed, 121 insertions(+), 126 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c
|
|
||||||
index 87297f4f691..1312eae2ff3 100644
|
|
||||||
--- a/src/lib-imap/imap-envelope.c
|
|
||||||
+++ b/src/lib-imap/imap-envelope.c
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
+#include "llist.h"
|
|
||||||
#include "istream.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "message-address.h"
|
|
||||||
@@ -127,7 +128,7 @@ static bool
|
|
||||||
imap_envelope_parse_addresses(const struct imap_arg *arg,
|
|
||||||
pool_t pool, struct message_address **addrs_r)
|
|
||||||
{
|
|
||||||
- struct message_address *first, *addr, *prev;
|
|
||||||
+ struct message_address *first, *last, *addr;
|
|
||||||
const struct imap_arg *list_args;
|
|
||||||
|
|
||||||
if (arg->type == IMAP_ARG_NIL) {
|
|
||||||
@@ -138,16 +139,12 @@ imap_envelope_parse_addresses(const struct imap_arg *arg,
|
|
||||||
if (!imap_arg_get_list(arg, &list_args))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
- first = addr = prev = NULL;
|
|
||||||
+ first = last = addr = NULL;
|
|
||||||
for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
|
|
||||||
if (!imap_envelope_parse_address
|
|
||||||
(list_args, pool, &addr))
|
|
||||||
return FALSE;
|
|
||||||
- if (first == NULL)
|
|
||||||
- first = addr;
|
|
||||||
- if (prev != NULL)
|
|
||||||
- prev->next = addr;
|
|
||||||
- prev = addr;
|
|
||||||
+ DLLIST2_APPEND(&first, &last, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
*addrs_r = first;
|
|
||||||
diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c
|
|
||||||
index fb06afae7b7..9d192799468 100644
|
|
||||||
--- a/src/lib-mail/message-address.c
|
|
||||||
+++ b/src/lib-mail/message-address.c
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
+#include "llist.h"
|
|
||||||
#include "str.h"
|
|
||||||
#include "strescape.h"
|
|
||||||
#include "smtp-address.h"
|
|
||||||
@@ -27,11 +28,7 @@ static void add_address(struct message_address_parser_context *ctx)
|
|
||||||
memcpy(addr, &ctx->addr, sizeof(ctx->addr));
|
|
||||||
i_zero(&ctx->addr);
|
|
||||||
|
|
||||||
- if (ctx->first_addr == NULL)
|
|
||||||
- ctx->first_addr = addr;
|
|
||||||
- else
|
|
||||||
- ctx->last_addr->next = addr;
|
|
||||||
- ctx->last_addr = addr;
|
|
||||||
+ DLLIST2_APPEND(&ctx->first_addr, &ctx->last_addr, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* quote with "" and escape all '\', '"' and "'" characters if need */
|
|
||||||
@@ -631,6 +628,7 @@ const char *message_address_first_to_string(const struct message_address *addr)
|
|
||||||
struct message_address first_addr;
|
|
||||||
|
|
||||||
first_addr = *addr;
|
|
||||||
+ first_addr.prev = NULL;
|
|
||||||
first_addr.next = NULL;
|
|
||||||
first_addr.route = NULL;
|
|
||||||
return message_address_to_string(&first_addr);
|
|
||||||
diff --git a/src/lib-mail/message-address.h b/src/lib-mail/message-address.h
|
|
||||||
index 8370397741c..85cff3dcc6f 100644
|
|
||||||
--- a/src/lib-mail/message-address.h
|
|
||||||
+++ b/src/lib-mail/message-address.h
|
|
||||||
@@ -18,7 +18,7 @@ enum message_address_parse_flags {
|
|
||||||
{name = NULL, NULL, "group", NULL}, ..., {NULL, NULL, NULL, NULL}
|
|
||||||
*/
|
|
||||||
struct message_address {
|
|
||||||
- struct message_address *next;
|
|
||||||
+ struct message_address *prev, *next;
|
|
||||||
|
|
||||||
/* display-name */
|
|
||||||
const char *name;
|
|
||||||
diff --git a/src/lib-mail/test-message-address.c b/src/lib-mail/test-message-address.c
|
|
||||||
index e6204bb0588..261cbfba70a 100644
|
|
||||||
--- a/src/lib-mail/test-message-address.c
|
|
||||||
+++ b/src/lib-mail/test-message-address.c
|
|
||||||
@@ -47,174 +47,174 @@ static void test_message_address(void)
|
|
||||||
} tests[] = {
|
|
||||||
/* user@domain -> <user@domain> */
|
|
||||||
{ "user@domain", "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "\"user\"@domain", "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "\"user name\"@domain", "<\"user name\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user name", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
|
||||||
{ "\"user@na\\\\me\"@domain", "<\"user@na\\\\me\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
|
||||||
{ "\"user\\\"name\"@domain", "<\"user\\\"name\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
|
||||||
{ "\"\"@domain", "<\"\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
|
||||||
{ "user", "<user>", "<user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "user", "", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "@domain", "<\"\"@domain>", "<MISSING_MAILBOX@domain>",
|
|
||||||
- { NULL, NULL, NULL, "", "domain", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
|
||||||
|
|
||||||
/* Display Name -> Display Name */
|
|
||||||
{ "Display Name", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "\"Display Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "Display \"Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "\"Display\" \"Name\"", "\"Display Name\"", "\"Display Name\" <MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "\"\"", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "", NULL, "", "", TRUE },
|
|
||||||
- { NULL, "", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "", NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, "", NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
|
|
||||||
/* <user@domain> -> <user@domain> */
|
|
||||||
{ "<user@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<\"user\"@domain>", "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<\"user name\"@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, NULL, "user name", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE }, 0 },
|
|
||||||
{ "<\"user@na\\\\me\"@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE }, 0 },
|
|
||||||
{ "<\"user\\\"name\"@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE }, 0 },
|
|
||||||
{ "<\"\"@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, NULL, "", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE }, 0 },
|
|
||||||
{ "<user>", NULL, "<user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "user", "", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "<@route>", "<@route:\"\">", "<INVALID_ROUTE:MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, "@route", "", "", TRUE },
|
|
||||||
- { NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route", "", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
|
|
||||||
/* user@domain (Display Name) -> "Display Name" <user@domain> */
|
|
||||||
{ "user@domain (DisplayName)", "DisplayName <user@domain>", NULL,
|
|
||||||
- { NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "user@domain (Display Name)", "\"Display Name\" <user@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "user@domain (Display\"Name)", "\"Display\\\"Name\" <user@domain>", NULL,
|
|
||||||
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "user (Display Name)", "\"Display Name\" <user>", "\"Display Name\" <user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "user", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "@domain (Display Name)", "\"Display Name\" <\"\"@domain>", "\"Display Name\" <MISSING_MAILBOX@domain>",
|
|
||||||
- { NULL, "Display Name", NULL, "", "domain", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "", "domain", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "MISSING_MAILBOX", "domain", TRUE }, 0 },
|
|
||||||
{ "user@domain ()", "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
|
|
||||||
/* Display Name <user@domain> -> "Display Name" <user@domain> */
|
|
||||||
{ "DisplayName <user@domain>", NULL, NULL,
|
|
||||||
- { NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "DisplayName", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "Display Name <user@domain>", "\"Display Name\" <user@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "\"Display Name\" <user@domain>", NULL, NULL,
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "\"Display\\\"Name\" <user@domain>", NULL, NULL,
|
|
||||||
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display\"Name", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "Display Name <user>", "\"Display Name\" <user>", "\"Display Name\" <user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", NULL, "user", "", TRUE },
|
|
||||||
- { NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", NULL, "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "\"\" <user@domain>", "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
|
|
||||||
/* <@route:user@domain> -> <@route:user@domain> */
|
|
||||||
{ "<@route:user@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, "@route", "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, "@route", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, "@route", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<@route,@route2:user@domain>", NULL, NULL,
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<@route@route2:user@domain>", "<@route,@route2:user@domain>", NULL,
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<@route@route2:user>", "<@route,@route2:user>", "<@route,@route2:user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "", TRUE },
|
|
||||||
- { NULL, NULL, "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "<@route@route2:\"\"@domain>", "<@route,@route2:\"\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, "@route,@route2", "", "domain", FALSE },
|
|
||||||
- { NULL, NULL, "@route,@route2", "", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, "@route,@route2", "", "domain", FALSE }, 0 },
|
|
||||||
|
|
||||||
/* Display Name <@route:user@domain> ->
|
|
||||||
"Display Name" <@route:user@domain> */
|
|
||||||
{ "Display Name <@route:user@domain>", "\"Display Name\" <@route:user@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", "@route", "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", "@route", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "Display Name <@route,@route2:user@domain>", "\"Display Name\" <@route,@route2:user@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "Display Name <@route@route2:user@domain>", "\"Display Name\" <@route,@route2:user@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "domain", FALSE }, 0 },
|
|
||||||
{ "Display Name <@route@route2:user>", "\"Display Name\" <@route,@route2:user>", "\"Display Name\" <@route,@route2:user@MISSING_DOMAIN>",
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "", TRUE },
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "", TRUE },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "user", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "Display Name <@route@route2:\"\"@domain>", "\"Display Name\" <@route,@route2:\"\"@domain>", NULL,
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "", "domain", FALSE },
|
|
||||||
- { NULL, "Display Name", "@route,@route2", "", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "Display Name", "@route,@route2", "", "domain", FALSE }, 0 },
|
|
||||||
|
|
||||||
/* other tests: */
|
|
||||||
{ "\"foo: <a@b>;,\" <user@domain>", NULL, NULL,
|
|
||||||
- { NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE },
|
|
||||||
- { NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
+ { NULL, NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE },
|
|
||||||
+ { NULL, NULL, "foo: <a@b>;,", NULL, "user", "domain", FALSE }, 0 },
|
|
||||||
{ "<>", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "<@>", "", "<INVALID_ROUTE:MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
- { NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, "INVALID_ROUTE", "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
|
|
||||||
/* Test against a out-of-bounds read bug - keep these two tests
|
|
||||||
together in this same order: */
|
|
||||||
{ "aaaa@", "<aaaa>", "<aaaa@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "aaaa", "", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "aaaa", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "aaaa", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "aaaa", "MISSING_DOMAIN", TRUE }, 0 },
|
|
||||||
{ "a(aa", "", "<MISSING_MAILBOX@MISSING_DOMAIN>",
|
|
||||||
- { NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
- { NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "", TRUE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "MISSING_MAILBOX", "MISSING_DOMAIN", TRUE },
|
|
||||||
TEST_MESSAGE_ADDRESS_FLAG_SKIP_LIST },
|
|
||||||
};
|
|
||||||
static struct message_address group_prefix = {
|
|
||||||
- NULL, NULL, NULL, "group", NULL, FALSE
|
|
||||||
+ NULL, NULL, NULL, NULL, "group", NULL, FALSE
|
|
||||||
};
|
|
||||||
static struct message_address group_suffix = {
|
|
||||||
- NULL, NULL, NULL, NULL, NULL, FALSE
|
|
||||||
+ NULL, NULL, NULL, NULL, NULL, NULL, FALSE
|
|
||||||
};
|
|
||||||
const struct message_address *addr;
|
|
||||||
string_t *str, *group;
|
|
||||||
@@ -327,7 +327,7 @@ static void test_message_address_nuls(void)
|
|
||||||
const unsigned char input[] =
|
|
||||||
"\"user\0nuls\\\0-esc\"@[domain\0nuls\\\0-esc] (comment\0nuls\\\0-esc)";
|
|
||||||
const struct message_address output = {
|
|
||||||
- NULL, "comment\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
|
||||||
+ NULL, NULL, "comment\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
|
||||||
"user\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc",
|
|
||||||
"[domain\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc]", FALSE
|
|
||||||
};
|
|
||||||
@@ -345,7 +345,7 @@ static void test_message_address_nuls_display_name(void)
|
|
||||||
const unsigned char input[] =
|
|
||||||
"\"displayname\0nuls\\\0-esc\" <\"user\0nuls\\\0-esc\"@[domain\0nuls\\\0-esc]>";
|
|
||||||
const struct message_address output = {
|
|
||||||
- NULL, "displayname\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
|
||||||
+ NULL, NULL, "displayname\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc", NULL,
|
|
||||||
"user\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc",
|
|
||||||
"[domain\xEF\xBF\xBDnuls\\\xEF\xBF\xBD-esc]", FALSE
|
|
||||||
};
|
|
||||||
@@ -369,7 +369,7 @@ static void test_message_address_non_strict_dots(void)
|
|
||||||
};
|
|
||||||
const struct message_address *addr;
|
|
||||||
struct message_address output = {
|
|
||||||
- NULL, NULL, NULL, "local-part",
|
|
||||||
+ NULL, NULL, NULL, NULL, "local-part",
|
|
||||||
"example.com", FALSE
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -421,29 +421,29 @@ static void test_message_address_path(void)
|
|
||||||
struct message_address addr;
|
|
||||||
} tests[] = {
|
|
||||||
{ "<>", NULL,
|
|
||||||
- { NULL, NULL, NULL, NULL, NULL, FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, NULL, NULL, FALSE } },
|
|
||||||
{ " < > ", "<>",
|
|
||||||
- { NULL, NULL, NULL, NULL, NULL, FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, NULL, NULL, FALSE } },
|
|
||||||
{ "<user@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
{ " <user@domain> ", "<user@domain>",
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
{ "user@domain", "<user@domain>",
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
{ " user@domain ", "<user@domain>",
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
{ "<\"user\"@domain>", "<user@domain>",
|
|
||||||
- { NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user", "domain", FALSE } },
|
|
||||||
{ "<\"user name\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user name", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user name", "domain", FALSE } },
|
|
||||||
{ "<\"user@na\\\\me\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user@na\\me", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user@na\\me", "domain", FALSE } },
|
|
||||||
{ "<\"user\\\"name\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "user\"name", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user\"name", "domain", FALSE } },
|
|
||||||
{ "<\"\"@domain>", NULL,
|
|
||||||
- { NULL, NULL, NULL, "", "domain", FALSE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "", "domain", FALSE } },
|
|
||||||
{ "<@source", "<>",
|
|
||||||
- { NULL, NULL, NULL, NULL, NULL, TRUE } },
|
|
||||||
+ { NULL, NULL, NULL, NULL, NULL, NULL, TRUE } },
|
|
||||||
};
|
|
||||||
const struct message_address *addr;
|
|
||||||
string_t *str;
|
|
||||||
|
|
||||||
From da61d20311da34f22944c6111a0b97ea2a1f8a47 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Tue, 30 Jan 2024 22:17:38 +0200
|
|
||||||
Subject: [PATCH 5/6] lib-mail: Add message_address_parse_full() and struct
|
|
||||||
message_address_list
|
|
||||||
|
|
||||||
---
|
|
||||||
src/lib-mail/message-address.c | 37 +++++++++++++---------
|
|
||||||
src/lib-mail/message-address.h | 10 ++++++
|
|
||||||
src/lib-mail/test-message-address.c | 48 +++++++++++++++++++++++++----
|
|
||||||
3 files changed, 75 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c
|
|
||||||
index 9d192799468..ae37014079a 100644
|
|
||||||
--- a/src/lib-mail/message-address.c
|
|
||||||
+++ b/src/lib-mail/message-address.c
|
|
||||||
@@ -13,7 +13,8 @@ struct message_address_parser_context {
|
|
||||||
pool_t pool;
|
|
||||||
struct rfc822_parser_context parser;
|
|
||||||
|
|
||||||
- struct message_address *first_addr, *last_addr, addr;
|
|
||||||
+ struct message_address addr;
|
|
||||||
+ struct message_address_list addr_list;
|
|
||||||
string_t *str;
|
|
||||||
|
|
||||||
bool fill_missing, non_strict_dots;
|
|
||||||
@@ -28,7 +29,7 @@ static void add_address(struct message_address_parser_context *ctx)
|
|
||||||
memcpy(addr, &ctx->addr, sizeof(ctx->addr));
|
|
||||||
i_zero(&ctx->addr);
|
|
||||||
|
|
||||||
- DLLIST2_APPEND(&ctx->first_addr, &ctx->last_addr, addr);
|
|
||||||
+ DLLIST2_APPEND(&ctx->addr_list.head, &ctx->addr_list.tail, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* quote with "" and escape all '\', '"' and "'" characters if need */
|
|
||||||
@@ -439,10 +440,11 @@ static int parse_path(struct message_address_parser_context *ctx)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static struct message_address *
|
|
||||||
+static void
|
|
||||||
message_address_parse_real(pool_t pool, const unsigned char *data, size_t size,
|
|
||||||
unsigned int max_addresses,
|
|
||||||
- enum message_address_parse_flags flags)
|
|
||||||
+ enum message_address_parse_flags flags,
|
|
||||||
+ struct message_address_list *list_r)
|
|
||||||
{
|
|
||||||
struct message_address_parser_context ctx;
|
|
||||||
|
|
||||||
@@ -461,7 +463,7 @@ message_address_parse_real(pool_t pool, const unsigned char *data, size_t size,
|
|
||||||
(void)parse_address_list(&ctx, max_addresses);
|
|
||||||
}
|
|
||||||
rfc822_parser_deinit(&ctx.parser);
|
|
||||||
- return ctx.first_addr;
|
|
||||||
+ *list_r = ctx.addr_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
@@ -481,7 +483,7 @@ message_address_parse_path_real(pool_t pool, const unsigned char *data,
|
|
||||||
ret = parse_path(&ctx);
|
|
||||||
|
|
||||||
rfc822_parser_deinit(&ctx.parser);
|
|
||||||
- *addr_r = ctx.first_addr;
|
|
||||||
+ *addr_r = ctx.addr_list.head;
|
|
||||||
return (ret < 0 ? -1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -490,17 +492,24 @@ message_address_parse(pool_t pool, const unsigned char *data, size_t size,
|
|
||||||
unsigned int max_addresses,
|
|
||||||
enum message_address_parse_flags flags)
|
|
||||||
{
|
|
||||||
- struct message_address *addr;
|
|
||||||
+ struct message_address_list list;
|
|
||||||
+ message_address_parse_full(pool, data, size, max_addresses, flags,
|
|
||||||
+ &list);
|
|
||||||
+ return list.head;
|
|
||||||
+}
|
|
||||||
|
|
||||||
+void message_address_parse_full(pool_t pool, const unsigned char *data,
|
|
||||||
+ size_t size, unsigned int max_addresses,
|
|
||||||
+ enum message_address_parse_flags flags,
|
|
||||||
+ struct message_address_list *list_r)
|
|
||||||
+{
|
|
||||||
if (pool->datastack_pool) {
|
|
||||||
- return message_address_parse_real(pool, data, size,
|
|
||||||
- max_addresses, flags);
|
|
||||||
- }
|
|
||||||
- T_BEGIN {
|
|
||||||
- addr = message_address_parse_real(pool, data, size,
|
|
||||||
- max_addresses, flags);
|
|
||||||
+ message_address_parse_real(pool, data, size,
|
|
||||||
+ max_addresses, flags, list_r);
|
|
||||||
+ } else T_BEGIN {
|
|
||||||
+ message_address_parse_real(pool, data, size,
|
|
||||||
+ max_addresses, flags, list_r);
|
|
||||||
} T_END;
|
|
||||||
- return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int message_address_parse_path(pool_t pool, const unsigned char *data,
|
|
||||||
diff --git a/src/lib-mail/message-address.h b/src/lib-mail/message-address.h
|
|
||||||
index 85cff3dcc6f..224f7a75605 100644
|
|
||||||
--- a/src/lib-mail/message-address.h
|
|
||||||
+++ b/src/lib-mail/message-address.h
|
|
||||||
@@ -31,12 +31,22 @@ struct message_address {
|
|
||||||
bool invalid_syntax;
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct message_address_list {
|
|
||||||
+ struct message_address *head, *tail;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* Parse message addresses from given data. Note that giving an empty string
|
|
||||||
will return NULL since there are no addresses. */
|
|
||||||
struct message_address *
|
|
||||||
message_address_parse(pool_t pool, const unsigned char *data, size_t size,
|
|
||||||
unsigned int max_addresses,
|
|
||||||
enum message_address_parse_flags flags);
|
|
||||||
+/* Same as message_address_parse(), but return message_address_list containing
|
|
||||||
+ both the first and the last address in the linked list. */
|
|
||||||
+void message_address_parse_full(pool_t pool, const unsigned char *data,
|
|
||||||
+ size_t size, unsigned int max_addresses,
|
|
||||||
+ enum message_address_parse_flags flags,
|
|
||||||
+ struct message_address_list *list_r);
|
|
||||||
|
|
||||||
/* Parse RFC 5322 "path" (Return-Path header) from given data. Returns -1 if
|
|
||||||
the path is invalid and 0 otherwise.
|
|
||||||
diff --git a/src/lib-mail/test-message-address.c b/src/lib-mail/test-message-address.c
|
|
||||||
index 261cbfba70a..54aa9a83101 100644
|
|
||||||
--- a/src/lib-mail/test-message-address.c
|
|
||||||
+++ b/src/lib-mail/test-message-address.c
|
|
||||||
@@ -19,8 +19,9 @@ static bool cmp_addr(const struct message_address *a1,
|
|
||||||
a1->invalid_syntax == a2->invalid_syntax;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static const struct message_address *
|
|
||||||
-test_parse_address(const char *input, bool fill_missing)
|
|
||||||
+static void
|
|
||||||
+test_parse_address_full(const char *input, bool fill_missing,
|
|
||||||
+ struct message_address_list *list_r)
|
|
||||||
{
|
|
||||||
const enum message_address_parse_flags flags =
|
|
||||||
fill_missing ? MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING : 0;
|
|
||||||
@@ -28,11 +29,18 @@ test_parse_address(const char *input, bool fill_missing)
|
|
||||||
if there's any out-of-bounds access */
|
|
||||||
size_t input_len = strlen(input);
|
|
||||||
unsigned char *input_dup = i_memdup(input, input_len);
|
|
||||||
- const struct message_address *addr =
|
|
||||||
- message_address_parse(pool_datastack_create(),
|
|
||||||
- input_dup, input_len, UINT_MAX, flags);
|
|
||||||
+ message_address_parse_full(pool_datastack_create(),
|
|
||||||
+ input_dup, input_len, UINT_MAX, flags,
|
|
||||||
+ list_r);
|
|
||||||
i_free(input_dup);
|
|
||||||
- return addr;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const struct message_address *
|
|
||||||
+test_parse_address(const char *input, bool fill_missing)
|
|
||||||
+{
|
|
||||||
+ struct message_address_list list;
|
|
||||||
+ test_parse_address_full(input, fill_missing, &list);
|
|
||||||
+ return list.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_message_address(void)
|
|
||||||
@@ -322,6 +330,33 @@ static void test_message_address(void)
|
|
||||||
test_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void test_message_address_list(void)
|
|
||||||
+{
|
|
||||||
+ test_begin("message address list");
|
|
||||||
+
|
|
||||||
+ const char *test_input =
|
|
||||||
+ "user1@example1.com, user2@example2.com, user3@example3.com";
|
|
||||||
+ const struct message_address wanted_addrs[] = {
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user1", "example1.com", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user2", "example2.com", FALSE },
|
|
||||||
+ { NULL, NULL, NULL, NULL, "user3", "example3.com", FALSE },
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ struct message_address_list list;
|
|
||||||
+ struct message_address *addr, *scanned_last_addr;
|
|
||||||
+ test_parse_address_full(test_input, FALSE, &list);
|
|
||||||
+ addr = list.head;
|
|
||||||
+ for (unsigned int i = 0; i < N_ELEMENTS(wanted_addrs); i++) {
|
|
||||||
+ test_assert_idx(cmp_addr(addr, &wanted_addrs[i]), i);
|
|
||||||
+ scanned_last_addr = addr;
|
|
||||||
+ addr = addr->next;
|
|
||||||
+ }
|
|
||||||
+ test_assert(list.tail == scanned_last_addr);
|
|
||||||
+ test_assert(addr == NULL);
|
|
||||||
+
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void test_message_address_nuls(void)
|
|
||||||
{
|
|
||||||
const unsigned char input[] =
|
|
||||||
@@ -521,6 +556,7 @@ int main(void)
|
|
||||||
{
|
|
||||||
static void (*const test_functions[])(void) = {
|
|
||||||
test_message_address,
|
|
||||||
+ test_message_address_list,
|
|
||||||
test_message_address_nuls,
|
|
||||||
test_message_address_nuls_display_name,
|
|
||||||
test_message_address_non_strict_dots,
|
|
||||||
|
|
||||||
From 1481c04f02df7647f520df65d63df7626bf0ee32 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Timo Sirainen <timo.sirainen@open-xchange.com>
|
|
||||||
Date: Fri, 9 Feb 2024 00:57:12 +0200
|
|
||||||
Subject: [PATCH 6/6] lib-mail, lib-imap: Optimize parsing large number of
|
|
||||||
address headers
|
|
||||||
|
|
||||||
Every header was appended to a linked list by walking through the whole
|
|
||||||
list, causing excessive CPU usage when the list became large enough.
|
|
||||||
Fixed by changing struct message_part_envelope to use struct
|
|
||||||
message_address_list, which stores also linked list tail pointers. This
|
|
||||||
allows quickly appending to the end of the linked list.
|
|
||||||
---
|
|
||||||
src/lib-imap/imap-envelope.c | 27 ++++++++++-------------
|
|
||||||
src/lib-mail/message-part-data.c | 17 +++++++-------
|
|
||||||
src/lib-mail/message-part-data.h | 6 +++--
|
|
||||||
src/lib-storage/index/index-search-mime.c | 4 ++--
|
|
||||||
4 files changed, 27 insertions(+), 27 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/lib-imap/imap-envelope.c b/src/lib-imap/imap-envelope.c
|
|
||||||
index 1312eae2ff3..da3177025a5 100644
|
|
||||||
--- a/src/lib-imap/imap-envelope.c
|
|
||||||
+++ b/src/lib-imap/imap-envelope.c
|
|
||||||
@@ -67,17 +67,17 @@ void imap_envelope_write(struct message_part_envelope *data,
|
|
||||||
}
|
|
||||||
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, data->from);
|
|
||||||
+ imap_write_address(str, data->from.head);
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, NVL(data->sender, data->from));
|
|
||||||
+ imap_write_address(str, NVL(data->sender.head, data->from.head));
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, NVL(data->reply_to, data->from));
|
|
||||||
+ imap_write_address(str, NVL(data->reply_to.head, data->from.head));
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, data->to);
|
|
||||||
+ imap_write_address(str, data->to.head);
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, data->cc);
|
|
||||||
+ imap_write_address(str, data->cc.head);
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
- imap_write_address(str, data->bcc);
|
|
||||||
+ imap_write_address(str, data->bcc.head);
|
|
||||||
|
|
||||||
str_append_c(str, ' ');
|
|
||||||
imap_append_nstring_nolf(str, data->in_reply_to);
|
|
||||||
@@ -126,28 +126,25 @@ imap_envelope_parse_address(const struct imap_arg *arg,
|
|
||||||
|
|
||||||
static bool
|
|
||||||
imap_envelope_parse_addresses(const struct imap_arg *arg,
|
|
||||||
- pool_t pool, struct message_address **addrs_r)
|
|
||||||
+ pool_t pool, struct message_address_list *addrs_r)
|
|
||||||
{
|
|
||||||
- struct message_address *first, *last, *addr;
|
|
||||||
+ struct message_address *addr;
|
|
||||||
const struct imap_arg *list_args;
|
|
||||||
|
|
||||||
- if (arg->type == IMAP_ARG_NIL) {
|
|
||||||
- *addrs_r = NULL;
|
|
||||||
+ i_zero(addrs_r);
|
|
||||||
+ if (arg->type == IMAP_ARG_NIL)
|
|
||||||
return TRUE;
|
|
||||||
- }
|
|
||||||
|
|
||||||
if (!imap_arg_get_list(arg, &list_args))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
- first = last = addr = NULL;
|
|
||||||
+ addr = NULL;
|
|
||||||
for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
|
|
||||||
if (!imap_envelope_parse_address
|
|
||||||
(list_args, pool, &addr))
|
|
||||||
return FALSE;
|
|
||||||
- DLLIST2_APPEND(&first, &last, addr);
|
|
||||||
+ DLLIST2_APPEND(&addrs_r->head, &addrs_r->tail, addr);
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- *addrs_r = first;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/src/lib-mail/message-part-data.c b/src/lib-mail/message-part-data.c
|
|
||||||
index a5771f87e2e..25019ab432d 100644
|
|
||||||
--- a/src/lib-mail/message-part-data.c
|
|
||||||
+++ b/src/lib-mail/message-part-data.c
|
|
||||||
@@ -4,6 +4,7 @@
|
|
||||||
#include "str.h"
|
|
||||||
#include "wildcard-match.h"
|
|
||||||
#include "array.h"
|
|
||||||
+#include "llist.h"
|
|
||||||
#include "rfc822-parser.h"
|
|
||||||
#include "rfc2231-parser.h"
|
|
||||||
#include "message-address.h"
|
|
||||||
@@ -176,7 +177,7 @@ void message_part_envelope_parse_from_header(pool_t pool,
|
|
||||||
{
|
|
||||||
struct message_part_envelope *d;
|
|
||||||
enum envelope_field field;
|
|
||||||
- struct message_address **addr_p, *addr;
|
|
||||||
+ struct message_address_list *addr_p, new_addr;
|
|
||||||
const char **str_p;
|
|
||||||
|
|
||||||
if (*data == NULL) {
|
|
||||||
@@ -234,18 +235,18 @@ void message_part_envelope_parse_from_header(pool_t pool,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addr_p != NULL) {
|
|
||||||
- addr = message_address_parse(pool, hdr->full_value,
|
|
||||||
- hdr->full_value_len,
|
|
||||||
- UINT_MAX,
|
|
||||||
- MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING);
|
|
||||||
+ message_address_parse_full(pool, hdr->full_value,
|
|
||||||
+ hdr->full_value_len,
|
|
||||||
+ UINT_MAX,
|
|
||||||
+ MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING,
|
|
||||||
+ &new_addr);
|
|
||||||
/* Merge multiple headers the same as if they were comma
|
|
||||||
separated in a single line. This is better from security
|
|
||||||
point of view, because attacker could intentionally write
|
|
||||||
addresses in a way that e.g. the first From header is
|
|
||||||
validated while MUA only shows the second From header. */
|
|
||||||
- while (*addr_p != NULL)
|
|
||||||
- addr_p = &(*addr_p)->next;
|
|
||||||
- *addr_p = addr;
|
|
||||||
+ DLLIST2_JOIN(&addr_p->head, &addr_p->tail,
|
|
||||||
+ &new_addr.head, &new_addr.tail);
|
|
||||||
} else if (str_p != NULL) {
|
|
||||||
*str_p = message_header_strdup(pool, hdr->full_value,
|
|
||||||
hdr->full_value_len);
|
|
||||||
diff --git a/src/lib-mail/message-part-data.h b/src/lib-mail/message-part-data.h
|
|
||||||
index 5ff9ffe1bc6..7ec878de68e 100644
|
|
||||||
--- a/src/lib-mail/message-part-data.h
|
|
||||||
+++ b/src/lib-mail/message-part-data.h
|
|
||||||
@@ -2,6 +2,7 @@
|
|
||||||
#define MESSAGE_PART_DATA_H
|
|
||||||
|
|
||||||
#include "message-part.h"
|
|
||||||
+#include "message-address.h"
|
|
||||||
|
|
||||||
#define MESSAGE_PART_DEFAULT_CHARSET "us-ascii"
|
|
||||||
|
|
||||||
@@ -14,8 +15,9 @@ struct message_part_param {
|
|
||||||
|
|
||||||
struct message_part_envelope {
|
|
||||||
const char *date, *subject;
|
|
||||||
- struct message_address *from, *sender, *reply_to;
|
|
||||||
- struct message_address *to, *cc, *bcc;
|
|
||||||
+
|
|
||||||
+ struct message_address_list from, sender, reply_to;
|
|
||||||
+ struct message_address_list to, cc, bcc;
|
|
||||||
|
|
||||||
const char *in_reply_to, *message_id;
|
|
||||||
};
|
|
||||||
diff --git a/src/lib-storage/index/index-search-mime.c b/src/lib-storage/index/index-search-mime.c
|
|
||||||
index da7e5e17092..3328ce98af1 100644
|
|
||||||
--- a/src/lib-storage/index/index-search-mime.c
|
|
||||||
+++ b/src/lib-storage/index/index-search-mime.c
|
|
||||||
@@ -205,7 +205,7 @@ seach_arg_mime_envelope_address_match(
|
|
||||||
enum mail_search_mime_arg_type type, const char *key,
|
|
||||||
const struct message_part_envelope *envelope)
|
|
||||||
{
|
|
||||||
- const struct message_address *addrs;
|
|
||||||
+ struct message_address_list addrs;
|
|
||||||
string_t *addrs_enc;
|
|
||||||
|
|
||||||
if (envelope == NULL)
|
|
||||||
@@ -239,7 +239,7 @@ seach_arg_mime_envelope_address_match(
|
|
||||||
probably be normalized directly in the struct message_address. */
|
|
||||||
|
|
||||||
addrs_enc = t_str_new(128);
|
|
||||||
- message_address_write(addrs_enc, addrs);
|
|
||||||
+ message_address_write(addrs_enc, addrs.head);
|
|
||||||
return (strstr(str_c(addrs_enc), key) != NULL ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,459 +0,0 @@
|
|||||||
diff -up dovecot-2.3.16/src/lib-mail/message-header-parser.c.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/message-header-parser.c
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/message-header-parser.c.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/message-header-parser.c 2024-08-20 23:29:25.214183880 +0200
|
|
||||||
@@ -17,6 +17,9 @@ struct message_header_parser_ctx {
|
|
||||||
string_t *name;
|
|
||||||
buffer_t *value_buf;
|
|
||||||
|
|
||||||
+ size_t header_block_max_size;
|
|
||||||
+ size_t header_block_total_size;
|
|
||||||
+
|
|
||||||
enum message_header_parser_flags flags;
|
|
||||||
bool skip_line:1;
|
|
||||||
bool has_nuls:1;
|
|
||||||
@@ -34,6 +37,7 @@ message_parse_header_init(struct istream
|
|
||||||
ctx->name = str_new(default_pool, 128);
|
|
||||||
ctx->flags = flags;
|
|
||||||
ctx->value_buf = buffer_create_dynamic(default_pool, 4096);
|
|
||||||
+ ctx->header_block_max_size = MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE;
|
|
||||||
i_stream_ref(input);
|
|
||||||
|
|
||||||
if (hdr_size != NULL)
|
|
||||||
@@ -41,6 +45,21 @@ message_parse_header_init(struct istream
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+message_parse_header_set_limit(struct message_header_parser_ctx *parser,
|
|
||||||
+ size_t header_block_max_size)
|
|
||||||
+{
|
|
||||||
+ parser->header_block_max_size = header_block_max_size;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+message_parse_header_lower_limit(struct message_header_parser_ctx *parser,
|
|
||||||
+ size_t header_block_max_size)
|
|
||||||
+{
|
|
||||||
+ if (header_block_max_size < parser->header_block_max_size)
|
|
||||||
+ message_parse_header_set_limit(parser, header_block_max_size);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void message_parse_header_deinit(struct message_header_parser_ctx **_ctx)
|
|
||||||
{
|
|
||||||
struct message_header_parser_ctx *ctx = *_ctx;
|
|
||||||
@@ -73,6 +92,7 @@ int message_parse_header_next(struct mes
|
|
||||||
/* new header line */
|
|
||||||
line->name_offset = ctx->input->v_offset;
|
|
||||||
colon_pos = UINT_MAX;
|
|
||||||
+ ctx->header_block_total_size += ctx->value_buf->used;
|
|
||||||
buffer_set_used_size(ctx->value_buf, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -326,33 +346,39 @@ int message_parse_header_next(struct mes
|
|
||||||
line->middle = str_data(ctx->name) + line->name_len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ line->value_len = I_MIN(line->value_len, ctx->header_block_max_size);
|
|
||||||
+ size_t line_value_size = line->value_len;
|
|
||||||
+ size_t header_total_used = ctx->header_block_total_size + ctx->value_buf->used;
|
|
||||||
+ size_t line_available = ctx->header_block_max_size <= header_total_used ? 0 :
|
|
||||||
+ ctx->header_block_max_size - header_total_used;
|
|
||||||
+ line_value_size = I_MIN(line_value_size, line_available);
|
|
||||||
+
|
|
||||||
if (!line->continued) {
|
|
||||||
/* first header line. make a copy of the line since we can't
|
|
||||||
really trust input stream not to lose it. */
|
|
||||||
- buffer_append(ctx->value_buf, line->value, line->value_len);
|
|
||||||
+ buffer_append(ctx->value_buf, line->value, line_value_size);
|
|
||||||
line->value = line->full_value = ctx->value_buf->data;
|
|
||||||
- line->full_value_len = line->value_len;
|
|
||||||
+ line->full_value_len = line->value_len = line_value_size;
|
|
||||||
} else if (line->use_full_value) {
|
|
||||||
/* continue saving the full value. */
|
|
||||||
if (last_no_newline) {
|
|
||||||
/* line is longer than fit into our buffer, so we
|
|
||||||
were forced to break it into multiple
|
|
||||||
message_header_lines */
|
|
||||||
- } else {
|
|
||||||
- if (last_crlf)
|
|
||||||
+ } else if (line_value_size > 1) {
|
|
||||||
+ if (last_crlf && line_value_size > 2)
|
|
||||||
buffer_append_c(ctx->value_buf, '\r');
|
|
||||||
buffer_append_c(ctx->value_buf, '\n');
|
|
||||||
}
|
|
||||||
if ((ctx->flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0 &&
|
|
||||||
line->value_len > 0 && line->value[0] != ' ' &&
|
|
||||||
- IS_LWSP(line->value[0])) {
|
|
||||||
+ IS_LWSP(line->value[0]) &&
|
|
||||||
+ line_value_size > 0) {
|
|
||||||
buffer_append_c(ctx->value_buf, ' ');
|
|
||||||
- buffer_append(ctx->value_buf,
|
|
||||||
- line->value + 1, line->value_len - 1);
|
|
||||||
- } else {
|
|
||||||
- buffer_append(ctx->value_buf,
|
|
||||||
- line->value, line->value_len);
|
|
||||||
- }
|
|
||||||
+ buffer_append(ctx->value_buf, line->value + 1, line_value_size - 1);
|
|
||||||
+ } else
|
|
||||||
+ buffer_append(ctx->value_buf, line->value, line_value_size);
|
|
||||||
+
|
|
||||||
line->full_value = ctx->value_buf->data;
|
|
||||||
line->full_value_len = ctx->value_buf->used;
|
|
||||||
} else {
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/message-header-parser.h.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/message-header-parser.h
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/message-header-parser.h.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/message-header-parser.h 2024-08-20 22:55:36.530652449 +0200
|
|
||||||
@@ -1,6 +1,9 @@
|
|
||||||
#ifndef MESSAGE_HEADER_PARSER_H
|
|
||||||
#define MESSAGE_HEADER_PARSER_H
|
|
||||||
|
|
||||||
+/* This can be overridden by message_parse_header_set_limit() */
|
|
||||||
+#define MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE ((size_t) 10 * 1024*1024)
|
|
||||||
+
|
|
||||||
#define IS_LWSP(c) \
|
|
||||||
((c) == ' ' || (c) == '\t')
|
|
||||||
|
|
||||||
@@ -48,6 +51,13 @@ message_parse_header_init(struct istream
|
|
||||||
enum message_header_parser_flags flags) ATTR_NULL(2);
|
|
||||||
void message_parse_header_deinit(struct message_header_parser_ctx **ctx);
|
|
||||||
|
|
||||||
+void
|
|
||||||
+message_parse_header_set_limit(struct message_header_parser_ctx *parser,
|
|
||||||
+ size_t header_block_max_size);
|
|
||||||
+void
|
|
||||||
+message_parse_header_lower_limit(struct message_header_parser_ctx *parser,
|
|
||||||
+ size_t header_block_max_size);
|
|
||||||
+
|
|
||||||
/* Read and return next header line. Returns 1 if header is returned, 0 if
|
|
||||||
input stream is non-blocking and more data needs to be read, -1 when all is
|
|
||||||
done or error occurred (see stream's error status). */
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/message-parser.c.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/message-parser.c
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/message-parser.c.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/message-parser.c 2024-08-20 22:55:36.531652458 +0200
|
|
||||||
@@ -617,7 +617,18 @@ static int parse_next_header(struct mess
|
|
||||||
}
|
|
||||||
if (ret < 0) {
|
|
||||||
/* no boundary */
|
|
||||||
+ size_t headers_available =
|
|
||||||
+ ctx->all_headers_max_size > ctx->all_headers_total_size ?
|
|
||||||
+ ctx->all_headers_max_size - ctx->all_headers_total_size : 0;
|
|
||||||
+ message_parse_header_lower_limit(ctx->hdr_parser_ctx, headers_available);
|
|
||||||
ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr);
|
|
||||||
+ if (ret > 0) {
|
|
||||||
+ if (!hdr->continues) {
|
|
||||||
+ ctx->all_headers_total_size += hdr->name_len;
|
|
||||||
+ ctx->all_headers_total_size += hdr->middle_len;
|
|
||||||
+ }
|
|
||||||
+ ctx->all_headers_total_size += hdr->value_len;
|
|
||||||
+ }
|
|
||||||
if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0)) {
|
|
||||||
ctx->want_count = i_stream_get_data_size(ctx->input) + 1;
|
|
||||||
return ret;
|
|
||||||
@@ -762,6 +773,9 @@ message_parser_init_int(struct istream *
|
|
||||||
ctx->max_total_mime_parts = set->max_total_mime_parts != 0 ?
|
|
||||||
set->max_total_mime_parts :
|
|
||||||
MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS;
|
|
||||||
+ ctx->all_headers_max_size = set->all_headers_max_size != 0 ?
|
|
||||||
+ set->all_headers_max_size :
|
|
||||||
+ MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE;
|
|
||||||
ctx->input = input;
|
|
||||||
i_stream_ref(input);
|
|
||||||
return ctx;
|
|
||||||
@@ -779,6 +793,7 @@ message_parser_init(pool_t part_pool, st
|
|
||||||
ctx->next_part = &ctx->part->children;
|
|
||||||
ctx->parse_next_block = parse_next_header_init;
|
|
||||||
ctx->total_parts_count = 1;
|
|
||||||
+ ctx->all_headers_total_size = 0;
|
|
||||||
i_array_init(&ctx->next_part_stack, 4);
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/message-parser.h.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/message-parser.h
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/message-parser.h.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/message-parser.h 2024-08-20 22:55:36.531652458 +0200
|
|
||||||
@@ -19,6 +19,7 @@ enum message_parser_flags {
|
|
||||||
|
|
||||||
#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100
|
|
||||||
#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000
|
|
||||||
+#define MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE ((size_t) 50 * 1024*1024)
|
|
||||||
|
|
||||||
struct message_parser_settings {
|
|
||||||
enum message_header_parser_flags hdr_flags;
|
|
||||||
@@ -30,6 +31,11 @@ struct message_parser_settings {
|
|
||||||
/* Maximum MIME parts in total.
|
|
||||||
0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */
|
|
||||||
unsigned int max_total_mime_parts;
|
|
||||||
+
|
|
||||||
+ /* Maximum bytes fore headers in top header plus all
|
|
||||||
+ MIME sections headers
|
|
||||||
+ 0 = MESSAGE_PARSER_DEFAULT_ALL_HEADERS_MAX_SIZE */
|
|
||||||
+ size_t all_headers_max_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct message_parser_ctx;
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/message-parser-private.h.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/message-parser-private.h
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/message-parser-private.h.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/message-parser-private.h 2024-08-20 22:55:36.531652458 +0200
|
|
||||||
@@ -30,6 +30,8 @@ struct message_parser_ctx {
|
|
||||||
enum message_parser_flags flags;
|
|
||||||
unsigned int max_nested_mime_parts;
|
|
||||||
unsigned int max_total_mime_parts;
|
|
||||||
+ size_t all_headers_max_size;
|
|
||||||
+ size_t all_headers_total_size;
|
|
||||||
|
|
||||||
char *last_boundary;
|
|
||||||
struct message_boundary *boundaries;
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/test-message-header-parser.c.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/test-message-header-parser.c
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/test-message-header-parser.c.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/test-message-header-parser.c 2024-08-20 23:23:18.169196280 +0200
|
|
||||||
@@ -332,6 +332,71 @@ static void test_message_header_parser_n
|
|
||||||
test_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define assert_parsed_field(line, expected, actual, len) STMT_START { \
|
|
||||||
+ test_assert_idx(memcmp(expected, actual, strlen(expected)) == 0, line); \
|
|
||||||
+ test_assert_cmp_idx(strlen(expected), ==, len, line); \
|
|
||||||
+} STMT_END
|
|
||||||
+
|
|
||||||
+/* NOTE: implicit variables: (parser, hdr) */
|
|
||||||
+#define assert_parse_line(line, exp_name, exp_value, exp_full) STMT_START { \
|
|
||||||
+ test_assert_idx(message_parse_header_next(parser, &hdr) > 0, line); \
|
|
||||||
+ assert_parsed_field(line, exp_name, hdr->name, hdr->name_len); \
|
|
||||||
+ assert_parsed_field(line, exp_value, hdr->value, hdr->value_len); \
|
|
||||||
+ assert_parsed_field(line, exp_full, hdr->full_value, hdr->full_value_len); \
|
|
||||||
+ if (hdr->continues) hdr->use_full_value = TRUE; \
|
|
||||||
+} STMT_END
|
|
||||||
+
|
|
||||||
+static const unsigned char test_message_header_truncation_input[] =
|
|
||||||
+ /*01*/ "header1: this is short\n"
|
|
||||||
+ /*02*/ "header2: this is multiline\n"
|
|
||||||
+ /*03*/ " and long 343638404244464850525456586062\n"
|
|
||||||
+ /*04*/ " 64666870727476788082848688909294969800\n"
|
|
||||||
+ /*05*/ " 02040608101214161820222426283032343638\n"
|
|
||||||
+ /*06*/ "header3: I should not appear at all\n"
|
|
||||||
+ /*07*/ "\n";
|
|
||||||
+
|
|
||||||
+static void test_message_header_truncation_clean_oneline(void)
|
|
||||||
+{
|
|
||||||
+ test_begin("message header parser truncate + CLEAN_ONELINE flag");
|
|
||||||
+ struct message_header_line *hdr = NULL;
|
|
||||||
+ struct istream *input = test_istream_create_data(test_message_header_truncation_input, sizeof(test_message_header_truncation_input));
|
|
||||||
+ struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE);
|
|
||||||
+ message_parse_header_set_limit(parser, 96);
|
|
||||||
+
|
|
||||||
+ assert_parse_line( 1, "header1", "this is short", "this is short");
|
|
||||||
+ assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
|
|
||||||
+ assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline and long 343638404244464850525456586062");
|
|
||||||
+ assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
|
|
||||||
+ assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline and long 343638404244464850525456586062 6466687072747678808284868");
|
|
||||||
+ assert_parse_line( 6, "header3", "", "");
|
|
||||||
+ test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);
|
|
||||||
+
|
|
||||||
+ message_parse_header_deinit(&parser);
|
|
||||||
+ i_stream_unref(&input);
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void test_message_header_truncation_flag0(void)
|
|
||||||
+{
|
|
||||||
+ test_begin("message header parser truncate + NO flags");
|
|
||||||
+ struct message_header_line *hdr = NULL;
|
|
||||||
+ struct istream *input = test_istream_create_data(test_message_header_truncation_input, sizeof(test_message_header_truncation_input));
|
|
||||||
+ struct message_header_parser_ctx *parser = message_parse_header_init(input, NULL, 0);
|
|
||||||
+ message_parse_header_set_limit(parser, 96);
|
|
||||||
+
|
|
||||||
+ assert_parse_line( 1, "header1", "this is short", "this is short");
|
|
||||||
+ assert_parse_line( 2, "header2", "this is multiline", "this is multiline");
|
|
||||||
+ assert_parse_line( 3, "header2", " and long 343638404244464850525456586062", "this is multiline\n and long 343638404244464850525456586062");
|
|
||||||
+ assert_parse_line( 4, "header2", " 64666870727476788082848688909294969800", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
|
|
||||||
+ assert_parse_line( 5, "header2", " 02040608101214161820222426283032343638", "this is multiline\n and long 343638404244464850525456586062\n 646668707274767880828486");
|
|
||||||
+ assert_parse_line( 6, "header3", "", "");
|
|
||||||
+ test_assert(message_parse_header_next(parser, &hdr) > 0 && hdr->eoh);
|
|
||||||
+
|
|
||||||
+ message_parse_header_deinit(&parser);
|
|
||||||
+ i_stream_unref(&input);
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
static void (*const test_functions[])(void) = {
|
|
||||||
@@ -341,6 +406,8 @@ int main(void)
|
|
||||||
test_message_header_parser_extra_cr_in_eoh,
|
|
||||||
test_message_header_parser_no_eoh,
|
|
||||||
test_message_header_parser_nul,
|
|
||||||
+ test_message_header_truncation_flag0,
|
|
||||||
+ test_message_header_truncation_clean_oneline,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
return test_run(test_functions);
|
|
||||||
diff -up dovecot-2.3.16/src/lib-mail/test-message-parser.c.CVE-2024-23185 dovecot-2.3.16/src/lib-mail/test-message-parser.c
|
|
||||||
--- dovecot-2.3.16/src/lib-mail/test-message-parser.c.CVE-2024-23185 2021-08-06 11:25:51.000000000 +0200
|
|
||||||
+++ dovecot-2.3.16/src/lib-mail/test-message-parser.c 2024-08-20 22:55:36.531652458 +0200
|
|
||||||
@@ -1369,6 +1369,158 @@ static const char input_msg[] =
|
|
||||||
test_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define test_assert_virtual_size(part) \
|
|
||||||
+ test_assert((part).virtual_size == (part).lines + (part).physical_size)
|
|
||||||
+
|
|
||||||
+#define test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size ) \
|
|
||||||
+STMT_START { \
|
|
||||||
+ test_assert((part)->flags == (flags_)); \
|
|
||||||
+ test_assert((part)->children_count == children); \
|
|
||||||
+ test_assert((part)->header_size.lines == h_lines); \
|
|
||||||
+ test_assert((part)->header_size.physical_size == h_size); \
|
|
||||||
+ test_assert((part)->body_size.lines == b_lines); \
|
|
||||||
+ test_assert((part)->body_size.physical_size == b_size); \
|
|
||||||
+ test_assert_virtual_size((part)->header_size); \
|
|
||||||
+ test_assert_virtual_size((part)->body_size); \
|
|
||||||
+} STMT_END
|
|
||||||
+
|
|
||||||
+static const enum message_part_flags FLAGS_MULTIPART =
|
|
||||||
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_MULTIPART;
|
|
||||||
+static const enum message_part_flags FLAGS_RFC822 =
|
|
||||||
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_MESSAGE_RFC822;
|
|
||||||
+static const enum message_part_flags FLAGS_TEXT =
|
|
||||||
+ MESSAGE_PART_FLAG_IS_MIME | MESSAGE_PART_FLAG_TEXT;
|
|
||||||
+
|
|
||||||
+static const char too_many_header_bytes_input_msg[] =
|
|
||||||
+ "Content-Type: multipart/mixed; boundary=\"1\"\n\n"
|
|
||||||
+ "--1\n"
|
|
||||||
+ "Content-Type: multipart/mixed; boundary=\"2\"\n\n"
|
|
||||||
+ "--2\n"
|
|
||||||
+ "Content-Type: message/rfc822\n\n"
|
|
||||||
+ "Content-Type: text/plain\n\n1-rfc822\n"
|
|
||||||
+ "--2\n"
|
|
||||||
+ "Content-Type: message/rfc822\n\n"
|
|
||||||
+ "Content-Type: text/plain\n\n2-rfc822\n"
|
|
||||||
+ "--1\n"
|
|
||||||
+ "Content-Type: message/rfc822\n\n"
|
|
||||||
+ "Content-Type: text/plain\n\n3-rfc822\n";
|
|
||||||
+
|
|
||||||
+static void test_message_parser_too_many_header_bytes_run(
|
|
||||||
+ const struct message_parser_settings *parser_set,
|
|
||||||
+ pool_t *pool_r, struct istream **input_r,
|
|
||||||
+ struct message_part **parts_r)
|
|
||||||
+{
|
|
||||||
+ *pool_r = pool_alloconly_create("message parser", 10240);
|
|
||||||
+ *input_r = test_istream_create(too_many_header_bytes_input_msg);
|
|
||||||
+ struct message_parser_ctx *parser = message_parser_init(*pool_r, *input_r, parser_set);
|
|
||||||
+
|
|
||||||
+ int ret;
|
|
||||||
+ struct message_block block ATTR_UNUSED;
|
|
||||||
+ while ((ret = message_parser_parse_next_block(parser, &block)) > 0);
|
|
||||||
+ test_assert(ret < 0);
|
|
||||||
+
|
|
||||||
+ message_parser_deinit(&parser, parts_r);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void test_message_parser_too_many_header_bytes_default(void)
|
|
||||||
+{
|
|
||||||
+ test_begin("message parser too many header bytes default");
|
|
||||||
+
|
|
||||||
+ pool_t pool;
|
|
||||||
+ struct istream *input;
|
|
||||||
+ struct message_part *part_root;
|
|
||||||
+ const struct message_parser_settings parser_set = { .all_headers_max_size = 0 };
|
|
||||||
+
|
|
||||||
+ test_message_parser_too_many_header_bytes_run(&parser_set, &pool, &input, &part_root);
|
|
||||||
+
|
|
||||||
+ // test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size )
|
|
||||||
+
|
|
||||||
+ test_assert_part(part_root, FLAGS_MULTIPART, 7, 2, 45, 21, 256);
|
|
||||||
+ test_assert(part_root->parent == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1 = part_root->children;
|
|
||||||
+ test_assert_part(part_1, FLAGS_MULTIPART, 4, 2, 45, 11, 137);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_1 = part_1->children;
|
|
||||||
+ test_assert_part(part_1_1, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_1_1 = part_1_1->children;
|
|
||||||
+ test_assert_part(part_1_1_1, FLAGS_TEXT, 0, 2, 26, 0, 8);
|
|
||||||
+
|
|
||||||
+ test_assert(part_1_1_1->next == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_2 = part_1_1->next;
|
|
||||||
+ test_assert_part(part_1_2, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_2_1 = part_1_2->children;
|
|
||||||
+ test_assert_part(part_1_2_1, FLAGS_TEXT, 0, 2, 26, 0, 8);
|
|
||||||
+
|
|
||||||
+ test_assert(part_1_2_1->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_assert(part_1_2->next == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_2 = part_1->next;
|
|
||||||
+ test_assert_part(part_2, FLAGS_RFC822, 1, 2, 30, 3, 35);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_2_1 = part_2->children;
|
|
||||||
+ test_assert_part(part_2_1, FLAGS_TEXT, 0, 2, 26, 1, 9);
|
|
||||||
+ test_assert(part_2_1->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_assert(part_2->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_assert(part_root->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_parsed_parts(input, part_root);
|
|
||||||
+ i_stream_unref(&input);
|
|
||||||
+ pool_unref(&pool);
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void test_message_parser_too_many_header_bytes_100(void)
|
|
||||||
+{
|
|
||||||
+ test_begin("message parser too many header bytes 100");
|
|
||||||
+
|
|
||||||
+ pool_t pool;
|
|
||||||
+ struct istream *input;
|
|
||||||
+ struct message_part *part_root;
|
|
||||||
+ const struct message_parser_settings parser_set = { .all_headers_max_size = 100 };
|
|
||||||
+
|
|
||||||
+ test_message_parser_too_many_header_bytes_run(&parser_set, &pool, &input, &part_root);
|
|
||||||
+
|
|
||||||
+ // test_assert_part(part, flags_, children, h_lines, h_size, b_lines, b_size )
|
|
||||||
+
|
|
||||||
+ test_assert_part(part_root, FLAGS_MULTIPART, 5, 2, 45, 21, 256);
|
|
||||||
+ test_assert(part_root->parent == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1 = part_root->children;
|
|
||||||
+ test_assert_part(part_1, FLAGS_MULTIPART, 3, 2, 45, 11, 137);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_1 = part_1->children;
|
|
||||||
+ test_assert_part(part_1_1, FLAGS_RFC822, 1, 2, 30, 2, 34);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_1_1 = part_1_1->children;
|
|
||||||
+ test_assert_part(part_1_1_1, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 26, 0, 8);
|
|
||||||
+
|
|
||||||
+ test_assert(part_1_1_1->next == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_1_2 = part_1_1->next;
|
|
||||||
+ test_assert_part(part_1_2, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 30, 2, 34);
|
|
||||||
+
|
|
||||||
+ test_assert(part_1_2->next == NULL);
|
|
||||||
+
|
|
||||||
+ struct message_part *part_2 = part_1->next;
|
|
||||||
+ test_assert_part(part_2, MESSAGE_PART_FLAG_IS_MIME, 0, 2, 30, 3, 35);
|
|
||||||
+
|
|
||||||
+ test_assert(part_2->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_assert(part_root->next == NULL);
|
|
||||||
+
|
|
||||||
+ test_parsed_parts(input, part_root);
|
|
||||||
+ i_stream_unref(&input);
|
|
||||||
+ pool_unref(&pool);
|
|
||||||
+ test_end();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
static void (*const test_functions[])(void) = {
|
|
||||||
@@ -1392,6 +1544,8 @@ int main(void)
|
|
||||||
test_message_parser_mime_part_limit_rfc822,
|
|
||||||
test_message_parser_mime_version,
|
|
||||||
test_message_parser_mime_version_missing,
|
|
||||||
+ test_message_parser_too_many_header_bytes_default,
|
|
||||||
+ test_message_parser_too_many_header_bytes_100,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
return test_run(test_functions);
|
|
@ -5,7 +5,7 @@ Name: dovecot
|
|||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 2.3.16
|
Version: 2.3.16
|
||||||
%global prever %{nil}
|
%global prever %{nil}
|
||||||
Release: 6%{?dist}
|
Release: 3%{?dist}
|
||||||
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
|
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
|
||||||
License: MIT and LGPLv2
|
License: MIT and LGPLv2
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
@ -50,24 +50,6 @@ Patch16: dovecot-2.3.16-keeplzma.patch
|
|||||||
# from upstream, for <= 2.3.19.1, rhbz#2106232
|
# from upstream, for <= 2.3.19.1, rhbz#2106232
|
||||||
Patch17: dovecot-2.3.19.1-7bad6a24.patch
|
Patch17: dovecot-2.3.19.1-7bad6a24.patch
|
||||||
|
|
||||||
# from upstream, for < 2.3.19.1, rhbz#2128857
|
|
||||||
Patch18: dovecot-2.3.18-9f300239..4596d399.patch
|
|
||||||
Patch19: dovecot-2.3.18-bdf447e4.patch
|
|
||||||
|
|
||||||
# from upstream, for < 2.3.21, RHEL-22854
|
|
||||||
Patch20: dovecot-2.3.16-d7705bc6.patch
|
|
||||||
|
|
||||||
# from upstream for < 2.3.21.1, RHEL-55206
|
|
||||||
# https://github.com/dovecot/core/compare/8e4c42d%5E...1481c04.patch
|
|
||||||
Patch21: dovecot-2.3.21.1-CVE-2024-23184.patch
|
|
||||||
|
|
||||||
# from upstream for < 2.3.21.1, RHEL-55219
|
|
||||||
# https://github.com/dovecot/core/compare/f020e13%5E...ce88c33.patch
|
|
||||||
Patch22: dovecot-2.3.21.1-CVE-2024-23185.patch
|
|
||||||
|
|
||||||
# fix test failing due to too long path with all the mock path prefixes
|
|
||||||
Patch23: dovecot-2.3.21-test-socket-path.patch
|
|
||||||
|
|
||||||
Source15: prestartscript
|
Source15: prestartscript
|
||||||
|
|
||||||
BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel
|
BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel
|
||||||
@ -163,25 +145,19 @@ This package provides the development files for dovecot.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}%{?prever} -a 8
|
%setup -q -n %{name}-%{version}%{?prever} -a 8
|
||||||
%patch -P 1 -p1 -b .default-settings
|
%patch1 -p1 -b .default-settings
|
||||||
%patch -P 2 -p1 -b .mkcert-permissions
|
%patch2 -p1 -b .mkcert-permissions
|
||||||
%patch -P 3 -p1 -b .mkcert-paths
|
%patch3 -p1 -b .mkcert-paths
|
||||||
%patch -P 6 -p1 -b .waitonline
|
%patch6 -p1 -b .waitonline
|
||||||
%patch -P 8 -p1 -b .initbysystemd
|
%patch8 -p1 -b .initbysystemd
|
||||||
%patch -P 9 -p1 -b .systemd_w_protectsystem
|
%patch9 -p1 -b .systemd_w_protectsystem
|
||||||
%patch -P 11 -p1 -b .aclfix
|
%patch11 -p1 -b .aclfix
|
||||||
%patch -P 13 -p1 -b .bigkey
|
%patch13 -p1 -b .bigkey
|
||||||
%patch -P 14 -p1 -b .opensslhmac
|
%patch14 -p1 -b .opensslhmac
|
||||||
%patch -P 15 -p1 -b .ftbfsbigend
|
%patch15 -p1 -b .ftbfsbigend
|
||||||
%patch -P 16 -p1 -b .keeplzma
|
%patch16 -p1 -b .keeplzma
|
||||||
%patch -P 17 -p1 -b .7bad6a24
|
%patch17 -p1 -b .7bad6a24
|
||||||
%patch -P 19 -p1 -b .bdf447e4
|
|
||||||
%patch -P 20 -p1 -b .d7705bc6
|
|
||||||
%patch -P 21 -p1 -b .CVE-2024-23184
|
|
||||||
%patch -P 22 -p1 -b .CVE-2024-23185
|
|
||||||
%patch -P 23 -p1 -b .test-socket-path
|
|
||||||
pushd dovecot-2*3-pigeonhole-%{pigeonholever}
|
pushd dovecot-2*3-pigeonhole-%{pigeonholever}
|
||||||
%patch -P 18 -p1 -b .9f300239..4596d399
|
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
@ -544,16 +520,6 @@ make check
|
|||||||
%{_libdir}/%{name}/dict/libdriver_pgsql.so
|
%{_libdir}/%{name}/dict/libdriver_pgsql.so
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Tue Aug 20 2024 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-6
|
|
||||||
- fix CVE-2024-23185: very large headers can cause resource exhaustion when parsing message (RHEL-55219)
|
|
||||||
- fix CVE-2024-23184: using a large number of address headers may trigger a denial of service (RHEL-55206)
|
|
||||||
|
|
||||||
* Fri Feb 16 2024 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-5
|
|
||||||
- fixes assert-crash when IMAP client uses QRESYNC (#RHEL-22854)
|
|
||||||
|
|
||||||
* Fri Aug 04 2023 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-4
|
|
||||||
- fix leaking mailboxes if virtual mailbox can't be opened (#2128857)
|
|
||||||
|
|
||||||
* Tue Jul 19 2022 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-3
|
* Tue Jul 19 2022 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-3
|
||||||
- fix possible privilege escalation when similar master and non-master passdbs are used (#2106231)
|
- fix possible privilege escalation when similar master and non-master passdbs are used (#2106231)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user