From: Stephan Bosch Date: Sat, 13 Jan 2018 10:51:24 +0000 (+0100) Subject: lib-smtp: address: Consistently allow address values to be NULL. X-Git-Tag: 2.3.9~2527 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aba05d93fe13aebb76d3ab8ca235a40f75b4afc4;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: address: Consistently allow address values to be NULL. If the address pointer is NULL or the localpart field is NULL or empty, it signifies that it is the NULL address "<>". In the case of smtp_address_equals(), this also likely fixes crashes at places where it may be used to compare "<>". --- diff --git a/src/lib-smtp/smtp-address.c b/src/lib-smtp/smtp-address.c index 53397b10ab..a277e22b7b 100644 --- a/src/lib-smtp/smtp-address.c +++ b/src/lib-smtp/smtp-address.c @@ -445,10 +445,13 @@ void smtp_address_detail_parse(pool_t pool, const char *delimiters, struct smtp_address *address, const char **username_r, char *delim_r, const char **detail_r) { - const char *localpart = address->localpart; + const char *localpart; const char *user, *p; size_t idx; + i_assert(!smtp_address_isnull(address)); + + localpart = address->localpart; user = localpart; *detail_r = ""; *delim_r = '\0'; @@ -501,7 +504,7 @@ void smtp_address_write(string_t *out, const unsigned char *p, *pend, *pblock; size_t begin; - if (address == NULL || address->localpart == NULL) + if (smtp_address_isnull(address)) return; begin = str_len(out); @@ -603,17 +606,15 @@ smtp_address_clone(pool_t pool, const struct smtp_address *src) size_t size, lpsize, dsize; char *data, *localpart, *domain; - if (src == NULL) + if (smtp_address_isnull(src)) return NULL; /* @UNSAFE */ lpsize = dsize = 0; size = sizeof(struct smtp_address); - if (src->localpart != NULL) { - lpsize = strlen(src->localpart) + 1; - size = MALLOC_ADD(size, lpsize); - } + lpsize = strlen(src->localpart) + 1; + size = MALLOC_ADD(size, lpsize); if (src->domain != NULL) { dsize = strlen(src->domain) + 1; size = MALLOC_ADD(size, dsize); @@ -661,6 +662,9 @@ smtp_address_clone_temp(const struct smtp_address *src) { struct smtp_address *new; + if (smtp_address_isnull(src)) + return NULL; + new = t_new(struct smtp_address, 1); new->localpart = t_strdup(src->localpart); new->domain = t_strdup(src->domain); @@ -692,6 +696,8 @@ smtp_address_add_detail(pool_t pool, const struct smtp_address *address, struct smtp_address *new_addr; const char delim[] = {delim_c, '\0'}; + i_assert(!smtp_address_isnull(address)); + new_addr = p_new(pool, struct smtp_address, 1); new_addr->localpart = p_strconcat(pool, address->localpart, delim, detail, NULL); @@ -707,6 +713,8 @@ smtp_address_add_detail_temp(const struct smtp_address *address, struct smtp_address *new_addr; const char delim[] = {delim_c, '\0'}; + i_assert(!smtp_address_isnull(address)); + new_addr = t_new(struct smtp_address, 1); new_addr->localpart = t_strconcat( address->localpart, delim, detail, NULL); @@ -718,9 +726,16 @@ smtp_address_add_detail_temp(const struct smtp_address *address, int smtp_address_cmp(const struct smtp_address *address1, const struct smtp_address *address2) { + bool null1, null2; int ret; - if ((ret=strcasecmp(address1->localpart, address2->localpart)) != 0) + null1 = smtp_address_isnull(address1); + null2 = smtp_address_isnull(address2); + if (null1) + return (null2 ? 0 : -1); + else if (null2) + return 1; + if ((ret=null_strcasecmp(address1->domain, address2->domain)) != 0) return ret; - return strcasecmp(address1->domain, address2->domain); + return null_strcmp(address1->localpart, address2->localpart); } diff --git a/src/lib-smtp/smtp-address.h b/src/lib-smtp/smtp-address.h index d685718462..a822b981d9 100644 --- a/src/lib-smtp/smtp-address.h +++ b/src/lib-smtp/smtp-address.h @@ -78,22 +78,26 @@ smtp_address_encode_path(const struct smtp_address *address) */ void smtp_address_init(struct smtp_address *address, - const char *localpart, const char *domain); + const char *localpart, const char *domain) ATTR_NULL(2,3); void smtp_address_init_from_msg(struct smtp_address *address, const struct message_address *msg_addr); struct smtp_address * -smtp_address_clone(pool_t pool, const struct smtp_address *address); +smtp_address_clone(pool_t pool, const struct smtp_address *address) + ATTR_NULL(2); struct smtp_address * -smtp_address_create(pool_t pool, const char *localpart, const char *domain); +smtp_address_create(pool_t pool, const char *localpart, const char *domain) + ATTR_NULL(2, 3); struct smtp_address * smtp_address_create_from_msg(pool_t pool, const struct message_address *msg_addr); struct smtp_address * -smtp_address_clone_temp(const struct smtp_address *address); +smtp_address_clone_temp(const struct smtp_address *address) + ATTR_NULL(1); struct smtp_address * -smtp_address_create_temp(const char *localpart, const char *domain); +smtp_address_create_temp(const char *localpart, const char *domain) + ATTR_NULL(2, 3); struct smtp_address * smtp_address_create_from_msg_temp(const struct message_address *msg_addr); @@ -105,9 +109,10 @@ smtp_address_add_detail_temp(const struct smtp_address *address, const char *detail, char delim_c); int smtp_address_cmp(const struct smtp_address *address1, - const struct smtp_address *address2); + const struct smtp_address *address2) + ATTR_NULL(1, 2); -static inline bool +static inline bool ATTR_NULL(1, 2) smtp_address_equals(const struct smtp_address *address1, const struct smtp_address *address2) { diff --git a/src/lib-smtp/test-smtp-address.c b/src/lib-smtp/test-smtp-address.c index 3f1fd2b0f0..6d937db991 100644 --- a/src/lib-smtp/test-smtp-address.c +++ b/src/lib-smtp/test-smtp-address.c @@ -203,17 +203,19 @@ static void test_smtp_path_parse_valid(void) test->input), ret > 0, error); if (ret > 0) { - if (address->localpart == NULL || - test->address.localpart == NULL) { - test_out(t_strdup_printf - ("address->localpart = %s", address->localpart), - (address->localpart == test->address.localpart)); + if (smtp_address_isnull(address) || + smtp_address_isnull(&test->address)) { + test_out("address = <>", + smtp_address_isnull(address) && + smtp_address_isnull(&test->address)); } else { test_out(t_strdup_printf ("address->localpart = \"%s\"", address->localpart), strcmp(address->localpart, test->address.localpart) == 0); } - if (address->domain == NULL || + if (smtp_address_isnull(address)) { + /* nothing */ + } else if (address->domain == NULL || test->address.domain == NULL) { test_out(t_strdup_printf ("address->domain = %s", address->domain), @@ -335,17 +337,19 @@ static void test_smtp_username_parse_valid(void) test->input), ret > 0, error); if (ret > 0) { - if (address->localpart == NULL || - test->address.localpart == NULL) { - test_out(t_strdup_printf - ("address->localpart = %s", address->localpart), - (address->localpart == test->address.localpart)); + if (smtp_address_isnull(address) || + smtp_address_isnull(&test->address)) { + test_out("address = <>", + smtp_address_isnull(address) && + smtp_address_isnull(&test->address)); } else { test_out(t_strdup_printf ("address->localpart = \"%s\"", address->localpart), strcmp(address->localpart, test->address.localpart) == 0); } - if (address->domain == NULL || + if (smtp_address_isnull(address)) { + /* nothing */ + } else if (address->domain == NULL || test->address.domain == NULL) { test_out(t_strdup_printf ("address->domain = %s", address->domain),