]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
examples: safer and more proper read callback logic
authorDaniel Stenberg <daniel@haxx.se>
Thu, 1 Jul 2021 07:21:40 +0000 (09:21 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 1 Jul 2021 12:27:12 +0000 (14:27 +0200)
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
docs/examples/smtp-authzid.c
docs/examples/smtp-mail.c
docs/examples/smtp-multi.c
docs/examples/smtp-ssl.c
docs/examples/smtp-tls.c

index 9c045710ab9325f8ab76bed5665d1a4fb4db8566..8dc6d23fdbbe0d1f5e6a5ed0aad0a5e8206f9d3f 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
 #define TO      "<addressee@example.net>"
 #define CC      "<info@example.org>"
 
-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: "
-  "<dcd7cb36-11db-487a-9f3a-e652a9458efd@rfcpedant.example.org>\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
-};
+  "<dcd7cb36-11db-487a-9f3a-e652a9458efd@rfcpedant.example.org>\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 */
index e5bb4932c8690d43239ccaf30bb6a6f4e378384f..e541f09058e99ea771a454e51718f77c63eaa6f5 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
 #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: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "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",
-  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) {
index 6ed7869ddd7350f6c348eac9314b6112ce6d3e8c..5159786c423ec013c39b72614276169517e2f4fa 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
 #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: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "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",
-  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) {
index 4d9eebb61359016a04e20316401c58ea3a684fb2..a52f0ae58ee4f5c251a1be61a7f95226b2fe360d 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * Note that this example requires libcurl 7.20.0 or above.
  */
 
-#define FROM     "<sender@example.com>"
-#define TO       "<recipient@example.com>"
-#define CC       "<info@example.com>"
+#define FROM_MAIL     "<sender@example.com>"
+#define TO_MAIL       "<recipient@example.com>"
+#define CC_MAIL       "<info@example.com>"
 
 #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: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "rfcpedant.example.org>\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
index a3cd8bb5dcee652e80bf557e265a0bbbfae394a8..6181bb035cb8d1a710b438a4895e71ca7835c052 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * Note that this example requires libcurl 7.20.0 or above.
  */
 
-#define FROM    "<sender@example.org>"
-#define TO      "<addressee@example.net>"
-#define CC      "<info@example.org>"
+#define FROM_MAIL     "<sender@example.com>"
+#define TO_MAIL       "<recipient@example.com>"
+#define CC_MAIL       "<info@example.com>"
 
-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: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "rfcpedant.example.org>\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
index d8f256186cf3ebb0bfaa1d42a935b493a9dce111..a9c45fa72473dfaeedcde1a69ecc324678196286 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * Note that this example requires libcurl 7.20.0 or above.
  */
 
-#define FROM    "<sender@example.org>"
-#define TO      "<addressee@example.net>"
-#define CC      "<info@example.org>"
+#define FROM_MAIL     "<sender@example.com>"
+#define TO_MAIL       "<recipient@example.com>"
+#define CC_MAIL       "<info@example.com>"
 
-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: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "rfcpedant.example.org>\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