From a37fc62e8bf90bf09d2556003235a4a11b5acf4e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 1 Jul 2021 09:21:40 +0200 Subject: [PATCH] examples: safer and more proper read callback logic The same callback code is used in: imap-append.c smtp-authzid.c smtp-mail.c smtp-multi.c smtp-ssl.c smtp-tls.c It should not assume that it can copy full lines into the buffer as it will encourage sloppy coding practices. Instead use byte-wise logic and check/acknowledge the buffer size appropriately. Reported-by: Harry Sintonen Fixes #7330 Closes #7331 --- docs/examples/imap-append.c | 47 ++++++++++++++------------------ docs/examples/smtp-authzid.c | 41 ++++++++++++++-------------- docs/examples/smtp-mail.c | 41 ++++++++++++++-------------- docs/examples/smtp-multi.c | 53 ++++++++++++++++++------------------ docs/examples/smtp-ssl.c | 53 ++++++++++++++++++------------------ docs/examples/smtp-tls.c | 53 ++++++++++++++++++------------------ 6 files changed, 139 insertions(+), 149 deletions(-) diff --git a/docs/examples/imap-append.c b/docs/examples/imap-append.c index 9c045710a..8dc6d23fd 100644 --- a/docs/examples/imap-append.c +++ b/docs/examples/imap-append.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -39,41 +39,42 @@ #define TO "" #define CC "" -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO "\r\n", - "From: " FROM "(Example User)\r\n", - "Cc: " CC "(Another example User)\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO "\r\n" + "From: " FROM "(Example User)\r\n" + "Cc: " CC "(Another example User)\r\n" "Message-ID: " - "\r\n", - "Subject: IMAP example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "\r\n" + "Subject: IMAP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -88,11 +89,8 @@ int main(void) curl = curl_easy_init(); if(curl) { - const char **p; long infilesize; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; /* Set username and password */ curl_easy_setopt(curl, CURLOPT_USERNAME, "user"); @@ -110,10 +108,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - infilesize = 0; - for(p = payload_text; *p; ++p) { - infilesize += (long)strlen(*p); - } + infilesize = strlen(payload_text); curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize); /* Perform the append */ diff --git a/docs/examples/smtp-authzid.c b/docs/examples/smtp-authzid.c index e5bb4932c..e541f0905 100644 --- a/docs/examples/smtp-authzid.c +++ b/docs/examples/smtp-authzid.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -47,41 +47,42 @@ #define SENDER_MAIL "Kurt " SENDER_ADDR #define TO_MAIL "A Receiver " TO_ADDR -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO_MAIL "\r\n", - "From: " FROM_MAIL "\r\n", - "Sender: " SENDER_MAIL "\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO_MAIL "\r\n" + "From: " FROM_MAIL "\r\n" + "Sender: " SENDER_MAIL "\r\n" "Message-ID: \r\n", - "Subject: SMTP example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "rfcpedant.example.org>\r\n" + "Subject: SMTP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -94,9 +95,7 @@ int main(void) CURL *curl; CURLcode res = CURLE_OK; struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; curl = curl_easy_init(); if(curl) { diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mail.c index 6ed7869dd..5159786c4 100644 --- a/docs/examples/smtp-mail.c +++ b/docs/examples/smtp-mail.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -44,41 +44,42 @@ #define TO_MAIL "A Receiver " TO_ADDR #define CC_MAIL "John CC Smith " CC_ADDR -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO_MAIL "\r\n", - "From: " FROM_MAIL "\r\n", - "Cc: " CC_MAIL "\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO_MAIL "\r\n" + "From: " FROM_MAIL "\r\n" + "Cc: " CC_MAIL "\r\n" "Message-ID: \r\n", - "Subject: SMTP example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "rfcpedant.example.org>\r\n" + "Subject: SMTP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -91,9 +92,7 @@ int main(void) CURL *curl; CURLcode res = CURLE_OK; struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; curl = curl_easy_init(); if(curl) { diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c index 4d9eebb61..a52f0ae58 100644 --- a/docs/examples/smtp-multi.c +++ b/docs/examples/smtp-multi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,47 +35,48 @@ * Note that this example requires libcurl 7.20.0 or above. */ -#define FROM "" -#define TO "" -#define CC "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" #define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000 -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO "\r\n", - "From: " FROM " (Example User)\r\n", - "Cc: " CC " (Another example User)\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO_MAIL "\r\n" + "From: " FROM_MAIL "\r\n" + "Cc: " CC_MAIL "\r\n" "Message-ID: \r\n", - "Subject: SMTP multi example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "rfcpedant.example.org>\r\n" + "Subject: SMTP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -107,9 +108,7 @@ int main(void) int still_running = 1; struct timeval mp_start; struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; curl_global_init(CURL_GLOBAL_DEFAULT); @@ -130,13 +129,13 @@ int main(void) * to the address in the reverse-path which triggered them. Otherwise, they * could cause an endless loop. See RFC 5321 Section 4.5.5 for more details. */ - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM); + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_MAIL); /* Add two recipients, in this particular case they correspond to the * To: and Cc: addressees in the header, but they could be any kind of * recipient. */ - recipients = curl_slist_append(recipients, TO); - recipients = curl_slist_append(recipients, CC); + recipients = curl_slist_append(recipients, TO_MAIL); + recipients = curl_slist_append(recipients, CC_MAIL); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); /* We're using a callback function to specify the payload (the headers and diff --git a/docs/examples/smtp-ssl.c b/docs/examples/smtp-ssl.c index a3cd8bb5d..6181bb035 100644 --- a/docs/examples/smtp-ssl.c +++ b/docs/examples/smtp-ssl.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,45 +37,46 @@ * Note that this example requires libcurl 7.20.0 or above. */ -#define FROM "" -#define TO "" -#define CC "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO "\r\n", - "From: " FROM " (Example User)\r\n", - "Cc: " CC " (Another example User)\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO_MAIL "\r\n" + "From: " FROM_MAIL "\r\n" + "Cc: " CC_MAIL "\r\n" "Message-ID: \r\n", - "Subject: SMTP SSL example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "rfcpedant.example.org>\r\n" + "Subject: SMTP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -88,9 +89,7 @@ int main(void) CURL *curl; CURLcode res = CURLE_OK; struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; curl = curl_easy_init(); if(curl) { @@ -129,13 +128,13 @@ int main(void) * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more * details. */ - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM); + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_MAIL); /* Add two recipients, in this particular case they correspond to the * To: and Cc: addressees in the header, but they could be any kind of * recipient. */ - recipients = curl_slist_append(recipients, TO); - recipients = curl_slist_append(recipients, CC); + recipients = curl_slist_append(recipients, TO_MAIL); + recipients = curl_slist_append(recipients, CC_MAIL); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); /* We're using a callback function to specify the payload (the headers and diff --git a/docs/examples/smtp-tls.c b/docs/examples/smtp-tls.c index d8f256186..a9c45fa72 100644 --- a/docs/examples/smtp-tls.c +++ b/docs/examples/smtp-tls.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,45 +37,46 @@ * Note that this example requires libcurl 7.20.0 or above. */ -#define FROM "" -#define TO "" -#define CC "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" -static const char *payload_text[] = { - "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n", - "To: " TO "\r\n", - "From: " FROM " (Example User)\r\n", - "Cc: " CC " (Another example User)\r\n", +static const char *payload_text = + "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" + "To: " TO_MAIL "\r\n" + "From: " FROM_MAIL "\r\n" + "Cc: " CC_MAIL "\r\n" "Message-ID: \r\n", - "Subject: SMTP TLS example message\r\n", - "\r\n", /* empty line to divide headers from body, see RFC5322 */ - "The body of the message starts here.\r\n", - "\r\n", - "It could be a lot of lines, could be MIME encoded, whatever.\r\n", - "Check RFC5322.\r\n", - NULL -}; + "rfcpedant.example.org>\r\n" + "Subject: SMTP example message\r\n" + "\r\n" /* empty line to divide headers from body, see RFC5322 */ + "The body of the message starts here.\r\n" + "\r\n" + "It could be a lot of lines, could be MIME encoded, whatever.\r\n" + "Check RFC5322.\r\n"; struct upload_status { - int lines_read; + size_t bytes_read; }; static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; + size_t room = size * nmemb; if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { return 0; } - data = payload_text[upload_ctx->lines_read]; + data = &payload_text[upload_ctx->bytes_read]; if(data) { size_t len = strlen(data); + if(room < len) + len = room; memcpy(ptr, data, len); - upload_ctx->lines_read++; + upload_ctx->bytes_read += len; return len; } @@ -88,9 +89,7 @@ int main(void) CURL *curl; CURLcode res = CURLE_OK; struct curl_slist *recipients = NULL; - struct upload_status upload_ctx; - - upload_ctx.lines_read = 0; + struct upload_status upload_ctx = { 0 }; curl = curl_easy_init(); if(curl) { @@ -131,13 +130,13 @@ int main(void) * they could cause an endless loop. See RFC 5321 Section 4.5.5 for more * details. */ - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM); + curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM_MAIL); /* Add two recipients, in this particular case they correspond to the * To: and Cc: addressees in the header, but they could be any kind of * recipient. */ - recipients = curl_slist_append(recipients, TO); - recipients = curl_slist_append(recipients, CC); + recipients = curl_slist_append(recipients, TO_MAIL); + recipients = curl_slist_append(recipients, CC_MAIL); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); /* We're using a callback function to specify the payload (the headers and