From: wwp Date: Mon, 16 Jan 2017 15:35:13 +0000 (+0100) Subject: Fix bug 3571, 'recipient list lost and truncated' X-Git-Tag: 3.15.0~112 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=989b3a3f51c691b0bb0fd48521063a8c76d269ce Fix bug 3571, 'recipient list lost and truncated' by replacing lots of fixed-size buffers with dynamically allocated ones. Also enforce checks by adding or fixing few sanity tests, fix returned value of some functions in some tricky cases. --- diff --git a/src/account.c b/src/account.c index 9c34f971c..9c44ef00a 100644 --- a/src/account.c +++ b/src/account.c @@ -1402,13 +1402,14 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel else if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) || folder_has_parent_of_type(msginfo->folder, F_OUTBOX) || folder_has_parent_of_type(msginfo->folder, F_DRAFT)) { - gchar from[BUFFSIZE]; + gchar *from = NULL; if (!procheader_get_header_from_msginfo - (msginfo, from, sizeof from, "From:")) { + (msginfo, &from, "From:")) { gchar *buf = from + strlen("From:"); extract_address(buf); account = account_find_from_address(buf, FALSE); - } + g_free(from); + } } /* select account by to: and cc: header if enabled */ if (reply_autosel) { @@ -1438,13 +1439,14 @@ PrefsAccount *account_get_reply_account(MsgInfo *msginfo, gboolean reply_autosel } } if (!account) { - gchar deliveredto[BUFFSIZE]; + gchar *deliveredto = NULL; if (!procheader_get_header_from_msginfo - (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) { + (msginfo, &deliveredto, "Delivered-To:")) { gchar *buf = deliveredto + strlen("Delivered-To:"); extract_address(buf); account = account_find_from_address(buf, FALSE); - } + g_free(deliveredto); + } } } diff --git a/src/common/utils.c b/src/common/utils.c index 10c3764ad..b13d09a67 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -1604,7 +1604,6 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc, g_warning("couldn't set insert file '%s' in body", value); } g_free(tmp); - tmp = NULL; } else if (attach && !g_ascii_strcasecmp(field, "attach")) { int i = 0; gchar *tmp = decode_uri_gdup(value); @@ -1613,7 +1612,6 @@ gint scan_mailto_url(const gchar *mailto, gchar **from, gchar **to, gchar **cc, g_print("Refusing to attach '%s', potential private data leak\n", tmp); g_free(tmp); - tmp = NULL; break; } } diff --git a/src/compose.c b/src/compose.c index bdb14b40a..3308f3cbc 100644 --- a/src/compose.c +++ b/src/compose.c @@ -2224,7 +2224,6 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch) GtkTextMark *mark; GtkTextIter iter; FILE *fp; - gchar buf[BUFFSIZE]; gboolean use_signing = FALSE; gboolean use_encryption = FALSE; gchar *privacy_system = NULL; @@ -2244,124 +2243,141 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch) if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) || folder_has_parent_of_type(msginfo->folder, F_DRAFT) || folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) { - gchar queueheader_buf[BUFFSIZE]; + gchar *queueheader_buf = NULL; gint id, param; /* Select Account from queue headers */ - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Account-Id:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Account-Id:")) { id = atoi(&queueheader_buf[strlen("X-Claws-Account-Id:")]); account = account_find_from_id(id); + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Sylpheed-Account-Id:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Sylpheed-Account-Id:")) { id = atoi(&queueheader_buf[strlen("X-Sylpheed-Account-Id:")]); account = account_find_from_id(id); + g_free(queueheader_buf); } - if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "NAID:")) { + if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "NAID:")) { id = atoi(&queueheader_buf[strlen("NAID:")]); account = account_find_from_id(id); + g_free(queueheader_buf); } - if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "MAID:")) { + if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "MAID:")) { id = atoi(&queueheader_buf[strlen("MAID:")]); account = account_find_from_id(id); + g_free(queueheader_buf); } - if (!account && !procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "S:")) { + if (!account && !procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "S:")) { account = account_find_from_address(queueheader_buf, FALSE); + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Sign:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Sign:")) { param = atoi(&queueheader_buf[strlen("X-Claws-Sign:")]); use_signing = param; - + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Sylpheed-Sign:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Sylpheed-Sign:")) { param = atoi(&queueheader_buf[strlen("X-Sylpheed-Sign:")]); use_signing = param; - + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Encrypt:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Encrypt:")) { param = atoi(&queueheader_buf[strlen("X-Claws-Encrypt:")]); use_encryption = param; + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Sylpheed-Encrypt:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Sylpheed-Encrypt:")) { param = atoi(&queueheader_buf[strlen("X-Sylpheed-Encrypt:")]); use_encryption = param; + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Auto-Wrapping:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Auto-Wrapping:")) { param = atoi(&queueheader_buf[strlen("X-Claws-Auto-Wrapping:")]); autowrap = param; + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Auto-Indent:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Auto-Indent:")) { param = atoi(&queueheader_buf[strlen("X-Claws-Auto-Indent:")]); autoindent = param; + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Claws-Privacy-System:")) { - privacy_system = g_strdup(&queueheader_buf[strlen("X-Claws-Privacy-System:")]); - } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Sylpheed-Privacy-System:")) { - privacy_system = g_strdup(&queueheader_buf[strlen("X-Sylpheed-Privacy-System:")]); - } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "X-Priority: ")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Privacy-System:")) { + privacy_system = g_strdup(&queueheader_buf[strlen("X-Claws-Privacy-System:")]); + g_free(queueheader_buf); + } + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Sylpheed-Privacy-System:")) { + privacy_system = g_strdup(&queueheader_buf[strlen("X-Sylpheed-Privacy-System:")]); + g_free(queueheader_buf); + } + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Priority: ")) { param = atoi(&queueheader_buf[strlen("X-Priority: ")]); /* mind the space */ priority = param; + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "RMID:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "RMID:")) { gchar **tokens = g_strsplit(&queueheader_buf[strlen("RMID:")], "\t", 0); - if (tokens[0] && tokens[1] && tokens[2]) { + if (tokens && tokens[0] && tokens[1] && tokens[2]) { FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]); if (orig_item != NULL) { replyinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]); } + g_strfreev(tokens); } - g_strfreev(tokens); + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, - sizeof(queueheader_buf), "FMID:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "FMID:")) { gchar **tokens = g_strsplit(&queueheader_buf[strlen("FMID:")], "\t", 0); - if (tokens[0] && tokens[1] && tokens[2]) { + if (tokens && tokens[0] && tokens[1] && tokens[2]) { FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]); if (orig_item != NULL) { fwdinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]); } + g_strfreev(tokens); } - g_strfreev(tokens); + g_free(queueheader_buf); } /* Get manual headers */ - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "X-Claws-Manual-Headers:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, + "X-Claws-Manual-Headers:")) { gchar *listmh = g_strdup(&queueheader_buf[strlen("X-Claws-Manual-Headers:")]); - if (*listmh != '\0') { + if (listmh && *listmh != '\0') { debug_print("Got manual headers: %s\n", listmh); manual_headers = procheader_entries_from_str(listmh); + g_free(listmh); } - g_free(listmh); + g_free(queueheader_buf); } } else { account = msginfo->folder->folder->account; } if (!account && prefs_common.reedit_account_autosel) { - gchar from[BUFFSIZE]; - if (!procheader_get_header_from_msginfo(msginfo, from, sizeof(from), "FROM:")) { - extract_address(from); - account = account_find_from_address(from, FALSE); - } - } - if (!account) { - account = cur_account; - } + gchar *from = NULL; + if (!procheader_get_header_from_msginfo(msginfo, &from, "FROM:")) { + extract_address(from); + account = account_find_from_address(from, FALSE); + g_free(from); + } + } + if (!account) { + account = cur_account; + } cm_return_val_if_fail(account != NULL, NULL); compose = compose_create(account, msginfo->folder, COMPOSE_REEDIT, batch); @@ -2388,21 +2404,23 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch) compose_extract_original_charset(compose); - if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) || + if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) || folder_has_parent_of_type(msginfo->folder, F_DRAFT) || folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) { - gchar queueheader_buf[BUFFSIZE]; + gchar *queueheader_buf = NULL; /* Set message save folder */ - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "SCF:")) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE); compose_set_save_to(compose, &queueheader_buf[4]); + g_free(queueheader_buf); } - if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "RRCPT:")) { + if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "RRCPT:")) { gint active = atoi(&queueheader_buf[strlen("RRCPT:")]); if (active) { cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE); } + g_free(queueheader_buf); } } @@ -2437,6 +2455,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch) } if (fp != NULL) { + gchar buf[BUFFSIZE]; gboolean prev_autowrap; GtkTextBuffer *buffer; BLOCK_WRAP(); @@ -5488,7 +5507,8 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest) { FILE *fp; size_t len; - gchar buf[BUFFSIZE]; + gchar *buf = NULL; + gchar rewrite_buf[BUFFSIZE]; int i = 0; gboolean skip = FALSE; gboolean err = FALSE; @@ -5509,24 +5529,34 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest) "X-Claws-Auto-Wrapping:", "X-Claws-Auto-Indent:", NULL }; + gint ret = 0; + if ((fp = g_fopen(compose->redirect_filename, "rb")) == NULL) { FILE_OP_ERROR(compose->redirect_filename, "fopen"); return -1; } - while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) { + while ((ret = procheader_get_one_field_asis(&buf, fp)) != -1) { skip = FALSE; for (i = 0; not_included[i] != NULL; i++) { if (g_ascii_strncasecmp(buf, not_included[i], strlen(not_included[i])) == 0) { skip = TRUE; + g_free(buf); + buf = NULL; break; } } - if (skip) + if (skip) { + g_free(buf); + buf = NULL; continue; - if (fputs(buf, fdest) == -1) + } + if (fputs(buf, fdest) == -1) { + g_free(buf); + buf = NULL; goto error; + } if (!prefs_common.redirect_keep_from) { if (g_ascii_strncasecmp(buf, "From:", @@ -5549,24 +5579,27 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest) } } + g_free(buf); + buf = NULL; if (fputs("\n", fdest) == -1) goto error; } - if (err) + if (err || ret == -1) goto error; if (compose_redirect_write_headers(compose, fdest)) goto error; - while ((len = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) { - if (fwrite(buf, sizeof(gchar), len, fdest) != len) + while ((len = fread(rewrite_buf, sizeof(gchar), sizeof(rewrite_buf), fp)) > 0) { + if (fwrite(rewrite_buf, sizeof(gchar), len, fdest) != len) goto error; } fclose(fp); return 0; + error: fclose(fp); @@ -11813,23 +11846,25 @@ static PrefsAccount *compose_find_account(MsgInfo *msginfo) } if (!account && prefs_common.forward_account_autosel) { - gchar cc[BUFFSIZE]; + gchar *cc = NULL; if (!procheader_get_header_from_msginfo - (msginfo, cc,sizeof cc , "Cc:")) { + (msginfo, &cc, "Cc:")) { gchar *buf = cc + strlen("Cc:"); - extract_address(buf); - account = account_find_from_address(buf, FALSE); - } + extract_address(buf); + account = account_find_from_address(buf, FALSE); + g_free(cc); + } } if (!account && prefs_common.forward_account_autosel) { - gchar deliveredto[BUFFSIZE]; + gchar *deliveredto = NULL; if (!procheader_get_header_from_msginfo - (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) { + (msginfo, &deliveredto, "Delivered-To:")) { gchar *buf = deliveredto + strlen("Delivered-To:"); - extract_address(buf); - account = account_find_from_address(buf, FALSE); - } + extract_address(buf); + account = account_find_from_address(buf, FALSE); + g_free(deliveredto); + } } if (!account) diff --git a/src/filtering.c b/src/filtering.c index 7b604a8e5..e4f3d0105 100644 --- a/src/filtering.c +++ b/src/filtering.c @@ -473,7 +473,7 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info) AddressBookFile *abf = NULL; ItemFolder *folder = NULL; #endif - gchar buf[BUFFSIZE]; + gchar *buf; Header *header; gint errors = 0; @@ -490,11 +490,11 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info) abf = book->rawDataSource; #endif /* get the header */ - if (procheader_get_header_from_msginfo(info, buf, - sizeof(buf), action->header) < 0) + if (procheader_get_header_from_msginfo(info, &buf, action->header) < 0) return FALSE; header = procheader_parse_header(buf); + g_free(buf); /* add all addresses that are not already in */ if (header && *header->body && (*header->body != '\0')) { diff --git a/src/matcher.c b/src/matcher.c index 64000e122..89b62327a 100644 --- a/src/matcher.c +++ b/src/matcher.c @@ -1287,10 +1287,10 @@ void matcherlist_free(MatcherList *cond) */ static void matcherlist_skip_headers(FILE *fp) { - gchar buf[BUFFSIZE]; + gchar *buf = NULL; - while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) - ; + while (procheader_get_one_field(&buf, fp, NULL) != -1) + g_free(buf); } /*! @@ -1470,9 +1470,10 @@ static gboolean matcherprop_criteria_message(MatcherProp *matcher) static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp) { GSList *l; - gchar buf[BUFFSIZE]; + gchar *buf = NULL; + gint ret; - while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) { + while ((ret = procheader_get_one_field(&buf, fp, NULL)) != -1) { for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) { MatcherProp *matcher = (MatcherProp *) l->data; gint match = MATCH_ANY; @@ -1537,10 +1538,14 @@ static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp) /* if the rule matched and the matchers are OR, no need to * check the others */ if (matcher->result && matcher->done) { - if (!matchers->bool_and) + if (!matchers->bool_and) { + g_free(buf); return TRUE; + } } } + g_free(buf); + buf = NULL; } return FALSE; diff --git a/src/messageview.c b/src/messageview.c index ac8ab4f2c..7052ff848 100644 --- a/src/messageview.c +++ b/src/messageview.c @@ -771,32 +771,38 @@ void messageview_init(MessageView *messageview) noticeview_hide(messageview->noticeview); } -static void notification_convert_header(gchar *dest, gint len, +static void notification_convert_header(gchar **dest, const gchar *src_, gint header_len) { char *src; cm_return_if_fail(src_ != NULL); - cm_return_if_fail(dest != NULL); - if (len < 1) return; + if (header_len < 1) { + *dest = g_strdup(""); + return; + } - Xstrndup_a(src, src_, len, return); + Xstrndup_a(src, src_, strlen(src_), return); remove_return(src); if (is_ascii_str(src)) { - strncpy2(dest, src, len); - dest[len - 1] = '\0'; + *dest = g_strdup(src); return; - } else - conv_encode_header(dest, len, src, header_len, FALSE); + } else { + *dest = g_malloc(BUFFSIZE); + if (*dest) + conv_encode_header(*dest, sizeof(dest), src, header_len, FALSE); + else + debug_print("notification_convert_header: alloc"); + } } static gint disposition_notification_send(MsgInfo *msginfo) { - gchar buf[BUFFSIZE]; + gchar *buf = NULL; gchar tmp[MAXPATHLEN + 1]; FILE *fp; GList *ac_list; @@ -811,6 +817,7 @@ static gint disposition_notification_send(MsgInfo *msginfo) gchar *foo = NULL; gboolean queued_removed = FALSE; gchar *boundary = NULL; + gchar buf_date[BUFFSIZE]; gchar *date = NULL; gchar *orig_to = NULL; gchar *enc_sub = NULL; @@ -827,8 +834,7 @@ static gint disposition_notification_send(MsgInfo *msginfo) else to = msginfo->extradata->returnreceiptto; - ok = procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf), - "Return-Path:"); + ok = procheader_get_header_from_msginfo(msginfo, &buf, "Return-Path:"); if (ok == 0) { gchar *to_addr = g_strdup(to); extract_address(to_addr); @@ -836,8 +842,7 @@ static gint disposition_notification_send(MsgInfo *msginfo) ok = strcasecmp(to_addr, buf); g_free(to_addr); } else { - g_strlcpy(buf, _(""), - sizeof(buf)); + buf = g_strdup(_("")); } if (ok != 0) { @@ -854,9 +859,13 @@ static gint disposition_notification_send(MsgInfo *msginfo) _("_Don't Send"), _("_Send"), NULL, FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT); g_free(message); - if (val != G_ALERTALTERNATE) + if (val != G_ALERTALTERNATE) { + g_free(buf); return -1; + } } + g_free(buf); + buf = NULL; ac_list = account_find_all_from_address(NULL, msginfo->to); ac_list = account_find_all_from_address(ac_list, msginfo->cc); @@ -959,17 +968,21 @@ static gint disposition_notification_send(MsgInfo *msginfo) goto FILE_ERROR; /* Date */ - get_rfc822_date(buf, sizeof(buf)); + get_rfc822_date(buf_date, sizeof(buf_date)); if (fprintf(fp, "Date: %s\n", buf) < 0) goto FILE_ERROR; /* From */ if (account->name && *account->name) { - notification_convert_header - (buf, sizeof(buf), account->name, - strlen("From: ")); - if (fprintf(fp, "From: %s <%s>\n", buf, account->address) < 0) + notification_convert_header(&buf, account->name, strlen("From: ")); + if (buf == NULL) + goto FILE_ERROR; + if (fprintf(fp, "From: %s <%s>\n", buf, account->address) < 0) { + g_free(buf); goto FILE_ERROR; + } + g_free(buf); + buf = NULL; } else if (fprintf(fp, "From: %s\n", account->address) < 0) goto FILE_ERROR; @@ -978,10 +991,15 @@ static gint disposition_notification_send(MsgInfo *msginfo) goto FILE_ERROR; /* Subject */ - notification_convert_header(buf, sizeof(buf), msginfo->subject, - strlen("Subject: ")); - if (fprintf(fp, "Subject: Disposition notification: %s\n", buf) < 0) + notification_convert_header(&buf, msginfo->subject, strlen("Subject: ")); + if (buf == NULL) + goto FILE_ERROR; + if (fprintf(fp, "Subject: Disposition notification: %s\n", buf) < 0) { + g_free(buf); goto FILE_ERROR; + } + g_free(buf); + buf = NULL; /* Message ID */ if (account->gen_msgid) { @@ -994,8 +1012,7 @@ static gint disposition_notification_send(MsgInfo *msginfo) } boundary = generate_mime_boundary("DN"); - get_rfc822_date(buf, sizeof(buf)); - date = g_strdup(buf); + date = g_strdup(buf_date); if (msginfo->to) { orig_to = g_strdup(msginfo->to); extract_address(orig_to); diff --git a/src/plugins/perl/perl_plugin.c b/src/plugins/perl/perl_plugin.c index 6db4c412d..fc2655511 100644 --- a/src/plugins/perl/perl_plugin.c +++ b/src/plugins/perl/perl_plugin.c @@ -651,7 +651,6 @@ static XS(XS_ClawsMail_filter_init) static XS(XS_ClawsMail_open_mail_file) { char *file; - gchar buf[BUFFSIZE]; dXSARGS; if(items != 0) { @@ -661,13 +660,13 @@ static XS(XS_ClawsMail_open_mail_file) file = procmsg_get_message_file_path(msginfo); if(!file) XSRETURN_UNDEF; - strncpy2(buf,file,sizeof(buf)); - g_free(file); - if((message_file = fopen(buf, "rb")) == NULL) { - FILE_OP_ERROR(buf, "fopen"); + if((message_file = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); g_warning("Perl Plugin: File open error in ClawsMail::C::open_mail_file"); + g_free(file); XSRETURN_UNDEF; } + g_free(file); } /* ClawsMail::C::close_mail_file */ @@ -686,7 +685,7 @@ static XS(XS_ClawsMail_close_mail_file) /* ClawsMail::C::get_next_header */ static XS(XS_ClawsMail_get_next_header) { - gchar buf[BUFFSIZE]; + gchar *buf; Header *header; dXSARGS; @@ -698,7 +697,7 @@ static XS(XS_ClawsMail_get_next_header) g_warning("Perl Plugin: Message file not open. Use ClawsMail::C::open_message_file first."); XSRETURN_EMPTY; } - if(procheader_get_one_field(buf, sizeof(buf), message_file, NULL) != -1) { + if(procheader_get_one_field(&buf, message_file, NULL) != -1) { header = procheader_parse_header(buf); EXTEND(SP, 2); if(header) { @@ -710,6 +709,7 @@ static XS(XS_ClawsMail_get_next_header) XST_mPV(0,""); XST_mPV(1,""); } + g_free(buf); XSRETURN(2); } else diff --git a/src/plugins/python/messageinfotype.c b/src/plugins/python/messageinfotype.c index ea983204c..2d20a3e96 100644 --- a/src/plugins/python/messageinfotype.c +++ b/src/plugins/python/messageinfotype.c @@ -35,8 +35,6 @@ #include -#define HEADER_CONTENT_SIZE BUFFSIZE - typedef struct { PyObject_HEAD MsgInfo *msginfo; @@ -194,7 +192,7 @@ static PyObject* get_header(PyObject *self, PyObject *args) char *header_str; char *header_str_dup; MsgInfo *msginfo; - gchar header_content[HEADER_CONTENT_SIZE]; + gchar *header_content = NULL; retval = PyArg_ParseTuple(args, "s", &header_str); if(!retval) @@ -203,7 +201,7 @@ static PyObject* get_header(PyObject *self, PyObject *args) msginfo = ((clawsmail_MessageInfoObject*)self)->msginfo; header_str_dup = g_strdup(header_str); - retval = procheader_get_header_from_msginfo(msginfo, header_content, HEADER_CONTENT_SIZE, header_str); + retval = procheader_get_header_from_msginfo(msginfo, &header_content, header_str); g_free(header_str_dup); if(retval == 0) { PyObject *header_content_object; @@ -219,9 +217,11 @@ static PyObject* get_header(PyObject *self, PyObject *args) while(*content_start == ' ') content_start++; header_content_object = Py_BuildValue("s", content_start); + g_free(header_content); return header_content_object; } else { + g_free(header_content); Py_RETURN_NONE; } } diff --git a/src/plugins/spam_report/spam_report.c b/src/plugins/spam_report/spam_report.c index e1987c53a..826281de8 100644 --- a/src/plugins/spam_report/spam_report.c +++ b/src/plugins/spam_report/spam_report.c @@ -141,11 +141,13 @@ static gchar *spamreport_strreplace(gchar *source, gchar *pattern, static gboolean check_debian_listid(MsgInfo *msginfo) { - gchar buf[1024]; - if (!procheader_get_header_from_msginfo(msginfo, buf, sizeof(buf), "List-Id:")) { + gchar *buf = NULL; + if (!procheader_get_header_from_msginfo(msginfo, &buf, "List-Id:") && buf != NULL) { if (strstr(buf, "lists.debian.org")) { + g_free(buf); return TRUE; } + g_free(buf); } return FALSE; } diff --git a/src/procheader.c b/src/procheader.c index a9bfa5ddd..2aa4e6f66 100644 --- a/src/procheader.c +++ b/src/procheader.c @@ -49,15 +49,15 @@ static gchar monthstr[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; typedef char *(*getlinefunc) (char *, size_t, void *); typedef int (*peekcharfunc) (void *); typedef int (*getcharfunc) (void *); -typedef gint (*get_one_field_func) (gchar *, size_t, void *, HeaderEntry[]); +typedef gint (*get_one_field_func) (gchar **, void *, HeaderEntry[]); -static gint string_get_one_field(gchar *buf, size_t len, char **str, +static gint string_get_one_field(gchar **buf, char **str, HeaderEntry hentry[]); static char *string_getline(char *buf, size_t len, char **str); static int string_peekchar(char **str); static int file_peekchar(FILE *fp); -static gint generic_get_one_field(gchar *buf, size_t len, void *data, +static gint generic_get_one_field(gchar **bufptr, void *data, HeaderEntry hentry[], getlinefunc getline, peekcharfunc peekchar, @@ -66,18 +66,18 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, gboolean full, gboolean decrypted); -gint procheader_get_one_field(gchar *buf, size_t len, FILE *fp, +gint procheader_get_one_field(gchar **buf, FILE *fp, HeaderEntry hentry[]) { - return generic_get_one_field(buf, len, fp, hentry, + return generic_get_one_field(buf, fp, hentry, (getlinefunc)fgets_crlf, (peekcharfunc)file_peekchar, TRUE); } -static gint string_get_one_field(gchar *buf, size_t len, char **str, +static gint string_get_one_field(gchar **buf, char **str, HeaderEntry hentry[]) { - return generic_get_one_field(buf, len, str, hentry, + return generic_get_one_field(buf, str, hentry, (getlinefunc)string_getline, (peekcharfunc)string_peekchar, TRUE); @@ -119,23 +119,48 @@ static int file_peekchar(FILE *fp) return ungetc(getc(fp), fp); } -static gint generic_get_one_field(gchar *buf, size_t len, void *data, +static gint generic_get_one_field(gchar **bufptr, void *data, HeaderEntry *hentry, getlinefunc getline, peekcharfunc peekchar, gboolean unfold) { + /* returns -1 in case of failure of any kind, whatever it's a parsing error + or an allocation error. if returns -1, *bufptr is always NULL, and vice-versa, + and if returning 0 (OK), *bufptr is always non-NULL, so callers just have to + test the return value + */ gint nexthead; gint hnum = 0; HeaderEntry *hp = NULL; + size_t len; + gchar *buf; +/* cm_return_val_if_fail(bufptr != NULL, -1); TODO */ + + len = BUFFSIZE; + buf = g_malloc(len); + if (buf == NULL) { + debug_print("generic_get_one_field: primary allocation error\n"); + *bufptr = NULL; + return -1; + } if (hentry != NULL) { /* skip non-required headers */ + /* and get hentry header line */ do { do { - if (getline(buf, len, data) == NULL) + if (getline(buf, len, data) == NULL) { + debug_print("generic_get_one_field: getline\n"); + g_free(buf); + *bufptr = NULL; return -1; - if (buf[0] == '\r' || buf[0] == '\n') + } + if (buf[0] == '\r' || buf[0] == '\n') { + debug_print("generic_get_one_field: empty line\n"); + g_free(buf); + *bufptr = NULL; return -1; + } } while (buf[0] == ' ' || buf[0] == '\t'); for (hp = hentry, hnum = 0; hp->name != NULL; @@ -146,8 +171,27 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data, } } while (hp->name == NULL); } else { - if (getline(buf, len, data) == NULL) return -1; - if (buf[0] == '\r' || buf[0] == '\n') return -1; + /* read first line */ + if (getline(buf, len, data) == NULL) { + debug_print("generic_get_one_field: getline\n"); + g_free(buf); + *bufptr = NULL; + return -1; + } + if (buf[0] == '\r' || buf[0] == '\n') { + debug_print("generic_get_one_field: empty line\n"); + g_free(buf); + *bufptr = NULL; + return -1; + } + } + /* reduce initial buffer to its useful part */ + len = strlen(buf)+1; + buf = g_realloc(buf, len); + if (buf == NULL) { + debug_print("generic_get_one_field: reallocation error\n"); + *bufptr = NULL; + return -1; } /* unfold line */ @@ -156,6 +200,9 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data, /* ([*WSP CRLF] 1*WSP) */ if (nexthead == ' ' || nexthead == '\t') { size_t buflen; + gchar *tmpbuf; + size_t tmplen; + gboolean skiptab = (nexthead == '\t'); /* trim previous trailing \n if requesting one header or * unfolding was requested */ @@ -164,15 +211,34 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data, buflen = strlen(buf); - /* concatenate next line */ - if ((len - buflen) > 2) { - if (getline(buf + buflen, len - buflen, data) == NULL) - break; - if (skiptab) { /* replace tab with space */ - *(buf + buflen) = ' '; - } - } else + /* read next line */ + tmpbuf = g_malloc(BUFFSIZE); + if (tmpbuf == NULL) { + debug_print("generic_get_one_field: secondary allocation error\n"); + g_free(buf); + *bufptr = NULL; + return -1; + } + if (getline(tmpbuf, BUFFSIZE, data) == NULL) { + g_free(tmpbuf); break; + } + tmplen = strlen(tmpbuf)+1; + + /* extend initial buffer and concatenate next line */ + len += tmplen; + buf = g_realloc(buf, len); + if (buf == NULL) { + debug_print("generic_get_one_field: reallocation error\n"); + g_free(buf); + *bufptr = NULL; + return -1; + } + memcpy(buf+buflen, tmpbuf, tmplen); + g_free(tmpbuf); + if (skiptab) { /* replace tab with space */ + *(buf + buflen) = ' '; + } } else { /* remove trailing new line */ strretchomp(buf); @@ -180,12 +246,14 @@ static gint generic_get_one_field(gchar *buf, size_t len, void *data, } } + *bufptr = buf; + return hnum; } -gint procheader_get_one_field_asis(gchar *buf, size_t len, FILE *fp) +gint procheader_get_one_field_asis(gchar **buf, FILE *fp) { - return generic_get_one_field(buf, len, fp, NULL, + return generic_get_one_field(buf, fp, NULL, (getlinefunc)fgets_crlf, (peekcharfunc)file_peekchar, FALSE); @@ -193,7 +261,7 @@ gint procheader_get_one_field_asis(gchar *buf, size_t len, FILE *fp) GPtrArray *procheader_get_header_array_asis(FILE *fp) { - gchar buf[BUFFSIZE]; + gchar *buf = NULL; GPtrArray *headers; Header *header; @@ -201,9 +269,11 @@ GPtrArray *procheader_get_header_array_asis(FILE *fp) headers = g_ptr_array_new(); - while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) { + while (procheader_get_one_field_asis(&buf, fp) != -1 && buf != NULL) { if ((header = procheader_parse_header(buf)) != NULL) g_ptr_array_add(headers, header); + g_free(buf); + buf = NULL; } return headers; @@ -214,6 +284,8 @@ void procheader_header_array_destroy(GPtrArray *harray) gint i; Header *header; + cm_return_if_fail(harray != NULL); + for (i = 0; i < harray->len; i++) { header = g_ptr_array_index(harray, i); procheader_header_free(header); @@ -290,6 +362,8 @@ Header * procheader_parse_header(gchar * buf) Header * header; gboolean addr_field = FALSE; + cm_return_val_if_fail(buf != NULL, NULL); + if ((*buf == ':') || (*buf == ' ')) return NULL; @@ -309,15 +383,14 @@ Header * procheader_parse_header(gchar * buf) void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[]) { - gchar buf[BUFFSIZE]; + gchar *buf = NULL; HeaderEntry *hp; gint hnum; gchar *p; if (hentry == NULL) return; - while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry)) - != -1) { + while ((hnum = procheader_get_one_field(&buf, fp, hentry)) != -1 && buf != NULL) { hp = hentry + hnum; p = buf + strlen(hp->name); @@ -331,6 +404,8 @@ void procheader_get_header_fields(FILE *fp, HeaderEntry hentry[]) hp->body = g_strconcat(tp, ", ", p, NULL); g_free(tp); } + g_free(buf); + buf = NULL; } } @@ -490,7 +565,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, gboolean full, gboolean decrypted) { MsgInfo *msginfo; - gchar buf[BUFFSIZE]; + gchar *buf = NULL; gchar *p, *tmp; gchar *hp; HeaderEntry *hentry; @@ -504,7 +579,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, hentry = procheader_get_headernames(full); if (MSG_IS_QUEUED(flags) || MSG_IS_DRAFT(flags)) { - while (get_one_field(buf, sizeof(buf), data, NULL) != -1) { + while (get_one_field(&buf, data, NULL) != -1 && buf != NULL) { if ((!strncmp(buf, "X-Claws-End-Special-Headers: 1", strlen("X-Claws-End-Special-Headers:"))) || (!strncmp(buf, "X-Sylpheed-End-Special-Headers: 1", @@ -519,8 +594,12 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, data = orig_data; else rewind((FILE *)data); + g_free(buf); + buf = NULL; break; } + g_free(buf); + buf = NULL; } } @@ -540,8 +619,7 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, avatar_hook_id = 0; } - while ((hnum = get_one_field(buf, sizeof(buf), data, hentry)) - != -1) { + while ((hnum = get_one_field(&buf, data, hentry)) != -1 && buf != NULL) { hp = buf + strlen(hentry[hnum].name); while (*hp == ' ' || *hp == '\t') hp++; @@ -743,6 +821,8 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags, hooks_invoke(AVATAR_HEADER_UPDATE_HOOKLIST, (gpointer)acd); g_free(acd); } + g_free(buf); + buf = NULL; } if (!msginfo->inreplyto && msginfo->references) @@ -1052,34 +1132,50 @@ void procheader_date_get_localtime(gchar *dest, gint len, const time_t timer) /* Added by Mel Hadasht on 27 Aug 2001 */ /* Get a header from msginfo */ -gint procheader_get_header_from_msginfo(MsgInfo *msginfo, gchar *buf, gint len, gchar *header) +gint procheader_get_header_from_msginfo(MsgInfo *msginfo, gchar **buf, gchar *header) { gchar *file; FILE *fp; HeaderEntry hentry[]={ { NULL, NULL, TRUE }, - { NULL, NULL, FALSE } }; + { NULL, NULL, FALSE } }; gint val; - hentry[0].name = header; - cm_return_val_if_fail(msginfo != NULL, -1); + cm_return_val_if_fail(buf != NULL, -1); + cm_return_val_if_fail(header != NULL, -1); + + hentry[0].name = header; + file = procmsg_get_message_file_path(msginfo); if ((fp = g_fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - g_free(file); - return -1; + FILE_OP_ERROR(file, "fopen"); + g_free(file); + g_free(*buf); + *buf = NULL; + return -1; + } + val = procheader_get_one_field(buf, fp, hentry); + if (buf == NULL) { + claws_unlink(file); + g_free(file); + g_free(*buf); + *buf = NULL; + return -1; } - val = procheader_get_one_field(buf,len, fp, hentry); if (fclose(fp) == EOF) { FILE_OP_ERROR(file, "fclose"); claws_unlink(file); g_free(file); + g_free(*buf); + *buf = NULL; return -1; } g_free(file); - if (val == -1) + if (val == -1) { + /* *buf is already NULL in that case, see procheader_get_one_field() */ return -1; + } return 0; } diff --git a/src/procheader.h b/src/procheader.h index e4cb92d7f..0588f305e 100644 --- a/src/procheader.h +++ b/src/procheader.h @@ -41,15 +41,10 @@ struct _Header gchar *body; }; -gint procheader_get_one_field (gchar *buf, - size_t len, +gint procheader_get_one_field (gchar **buf, FILE *fp, HeaderEntry hentry[]); -gint procheader_get_one_field_asis (gchar *buf, - size_t len, - FILE *fp); -gchar *procheader_get_unfolded_line (gchar *buf, - size_t len, +gint procheader_get_one_field_asis (gchar **buf, FILE *fp); GPtrArray *procheader_get_header_array_asis (FILE *fp); @@ -89,8 +84,7 @@ gboolean procheader_headername_equal (char * hdr1, char * hdr2); void procheader_header_free (Header * header); gint procheader_get_header_from_msginfo (MsgInfo *msginfo, - gchar *buf, - gint len, + gchar **buf, gchar *header); HeaderEntry *procheader_entries_from_str(const gchar *str); diff --git a/src/procmsg.c b/src/procmsg.c index aa3c9a829..c9b077eb1 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -724,7 +724,7 @@ static PrefsAccount *procmsg_get_account_from_file(const gchar *file) PrefsAccount *mailac = NULL; FILE *fp; int hnum; - gchar buf[BUFFSIZE]; + gchar *buf = NULL; static HeaderEntry qentry[] = {{"S:", NULL, FALSE}, {"SSV:", NULL, FALSE}, {"R:", NULL, FALSE}, @@ -750,14 +750,15 @@ static PrefsAccount *procmsg_get_account_from_file(const gchar *file) return NULL; } - while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry)) - != -1) { + while ((hnum = procheader_get_one_field(&buf, fp, qentry)) != -1 && buf != NULL) { gchar *p = buf + strlen(qentry[hnum].name); if (hnum == Q_MAIL_ACCOUNT_ID) { mailac = account_find_from_id(atoi(p)); break; } + g_free(buf); + buf = NULL; } fclose(fp); return mailac; @@ -1542,7 +1543,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses gchar *savecopyfolder = NULL; gchar *replymessageid = NULL; gchar *fwdmessageid = NULL; - gchar buf[BUFFSIZE]; + gchar *buf; gint hnum; PrefsAccount *mailac = NULL, *newsac = NULL; gboolean encrypt = FALSE; @@ -1559,8 +1560,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses return -1; } - while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry)) - != -1) { + while ((hnum = procheader_get_one_field(&buf, fp, qentry)) != -1 && buf != NULL) { gchar *p = buf + strlen(qentry[hnum].name); switch (hnum) { @@ -1607,6 +1607,8 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses goto send_mail; /* can't "break;break;" */ } } + g_free(buf); + send_mail: filepos = ftell(fp); if (filepos < 0) { @@ -1679,6 +1681,7 @@ send_mail: if (newsgroup_list && newsac && (mailval == 0)) { Folder *folder; gchar *tmp = NULL; + gchar buf[BUFFSIZE]; FILE *tmpfp; /* write to temporary file */