]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tests/server/getpart.c: properly deal with binary data containing NUL bytes
authorFabian Keil <fk@fabiankeil.de>
Sun, 24 Jan 2021 14:27:00 +0000 (15:27 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 7 Jan 2022 09:01:44 +0000 (10:01 +0100)
tests/server/getpart.c

index 32b55bc6190a594fcf85cc557bf61e2965c0d72f..68158530b12393619961b1443c5c7ff18cc828ac 100644 (file)
@@ -95,6 +95,33 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+/*
+ * line_length()
+ *
+ * Counts the number of characters in a line including a new line.
+ * Unlike strlen() it does not stop at nul bytes.
+ *
+ */
+static size_t line_length(const char *buffer, int bytestocheck)
+{
+  size_t length = 1;
+
+  while(*buffer != '\n' && --bytestocheck) {
+    length++;
+    buffer++;
+  }
+  if(*buffer != '\n') {
+    /*
+     * We didn't find a new line so the last byte must be a
+     * '\0' character inserted by fgets() which we should not
+     * count.
+     */
+    length--;
+  }
+
+  return length;
+}
+
 /*
  * readline()
  *
@@ -113,7 +140,8 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
  *   GPE_OK
  */
 
-static int readline(char **buffer, size_t *bufsize, FILE *stream)
+static int readline(char **buffer, size_t *bufsize, size_t *length,
+                    FILE *stream)
 {
   size_t offset = 0;
   char *newptr;
@@ -126,17 +154,16 @@ static int readline(char **buffer, size_t *bufsize, FILE *stream)
   }
 
   for(;;) {
-    size_t length;
     int bytestoread = curlx_uztosi(*bufsize - offset);
 
     if(!fgets(*buffer + offset, bytestoread, stream))
       return (offset != 0) ? GPE_OK : GPE_END_OF_FILE;
 
-    length = offset + strlen(*buffer + offset);
-    if(*(*buffer + length - 1) == '\n')
+    *length = offset + line_length(*buffer + offset, bytestoread);
+    if(*(*buffer + *length - 1) == '\n')
       break;
-    offset = length;
-    if(length < *bufsize - 1)
+    offset = *length;
+    if(*length < *bufsize - 1)
       continue;
 
     newptr = realloc(*buffer, *bufsize * 2);
@@ -179,10 +206,10 @@ static int appenddata(char  **dst_buf,   /* dest buffer */
                       size_t *dst_len,   /* dest buffer data length */
                       size_t *dst_alloc, /* dest buffer allocated size */
                       char   *src_buf,   /* source buffer */
+                      size_t  src_len,   /* source buffer length */
                       int     src_b64)   /* != 0 if source is base64 encoded */
 {
   size_t need_alloc = 0;
-  size_t src_len = strlen(src_buf);
 
   if(!src_len)
     return GPE_OK;
@@ -293,6 +320,7 @@ int getpart(char **outbuf, size_t *outlen,
   } len;
   size_t bufsize = 0;
   size_t outalloc = 256;
+  size_t datalen;
   int in_wanted_part = 0;
   int base64 = 0;
   int error;
@@ -313,7 +341,7 @@ int getpart(char **outbuf, size_t *outlen,
 
   couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
 
-  while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) {
+  while((error = readline(&buffer, &bufsize, &datalen, stream)) == GPE_OK) {
 
     ptr = buffer;
     EAT_SPACE(ptr);
@@ -321,7 +349,8 @@ int getpart(char **outbuf, size_t *outlen,
     if('<' != *ptr) {
       if(in_wanted_part) {
         show(("=> %s", buffer));
-        error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
+        error = appenddata(outbuf, outlen, &outalloc, buffer, datalen,
+                           base64);
         if(error)
           break;
       }
@@ -459,7 +488,7 @@ int getpart(char **outbuf, size_t *outlen,
 
     if(in_wanted_part) {
       show(("=> %s", buffer));
-      error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
+      error = appenddata(outbuf, outlen, &outalloc, buffer, datalen, base64);
       if(error)
         break;
     }