Skip to content

Commit

Permalink
lib-storage: Fix bodystructure parsing crash if header is parsed twice
Browse files Browse the repository at this point in the history
The second parsing will recreate the parser_ctx, discarding the old parsed
message_part.data for the header. On the second parsing
save_bodystructure_header=FALSE so the message_part.data isn't filled for
the header. Later on the bodystructure parsing assumes the data is set,
and crashes.

This only happened with mail_attachment_detection_options=add-flags-on-save
and Sieve script that first accessed a non-cached header and then used the
"body" extension.

Fixes segfault and also:
Panic: file imap-bodystructure.c: line 116 (part_write_body_multipart): assertion failed: (part->data != NULL)
  • Loading branch information
sirainen committed Jul 25, 2018
1 parent 9753fd9 commit a14b731
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 3 deletions.
8 changes: 7 additions & 1 deletion src/lib-storage/index/index-mail-headers.c
Expand Up @@ -313,7 +313,7 @@ void index_mail_parse_header(struct message_part *part,
if (data->save_bodystructure_header) {
i_assert(!data->save_bodystructure_body ||
data->parser_ctx != NULL);
data->save_bodystructure_header = FALSE;
data->parsed_bodystructure_header = TRUE;
}
return;
}
Expand Down Expand Up @@ -414,6 +414,12 @@ static void index_mail_init_parser(struct index_mail *mail)
index_mail_set_message_parts_corrupted(&mail->mail.mail, error);
data->parts = NULL;
}
if (data->parts == NULL) {
/* The previous parsing didn't finish, so we're
re-parsing the header. The new parts don't have data
filled anymore. */
data->parsed_bodystructure_header = FALSE;
}
}

if (data->parts == NULL) {
Expand Down
5 changes: 3 additions & 2 deletions src/lib-storage/index/index-mail.c
Expand Up @@ -1193,7 +1193,7 @@ static int index_mail_parse_body(struct index_mail *mail,
if (data->save_bodystructure_body) {
/* bodystructure header is parsed, we want the body's mime
headers too */
i_assert(!data->save_bodystructure_header);
i_assert(data->parsed_bodystructure_header);
message_parser_parse_body(data->parser_ctx,
parse_bodystructure_part_header,
mail->mail.data_pool);
Expand Down Expand Up @@ -1346,7 +1346,8 @@ static int index_mail_parse_bodystructure(struct index_mail *mail,
a string */
index_mail_body_parsed_cache_bodystructure(mail, field);
} else {
if (data->save_bodystructure_header ||
if ((data->save_bodystructure_header &&
!data->parsed_bodystructure_header) ||
!data->save_bodystructure_body ||
field == MAIL_CACHE_BODY_SNIPPET) {
/* we haven't parsed the header yet */
Expand Down
1 change: 1 addition & 0 deletions src/lib-storage/index/index-mail.h
Expand Up @@ -118,6 +118,7 @@ struct index_mail_data {
bool save_body_snippet:1;
bool stream_has_only_header:1;
bool parsed_bodystructure:1;
bool parsed_bodystructure_header:1;
bool hdr_size_set:1;
bool body_size_set:1;
bool messageparts_saved_to_cache:1;
Expand Down

0 comments on commit a14b731

Please sign in to comment.