curl_formget: fix FILE * leak
authorDaniel Stenberg <daniel@haxx.se>
Mon, 13 Jun 2011 20:32:00 +0000 (22:32 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 13 Jun 2011 20:32:00 +0000 (22:32 +0200)
Properly deal with the fact that the last fread() call most probably is
a short read, and when using callbacks in fact all calls can be short
reads. No longer consider a file read done until it returns a 0 from the
read function.

Reported by: Aaron Orenstein
Bug: http://curl.haxx.se/mail/lib-2011-06/0048.html

lib/formdata.c
tests/data/test1308
tests/unit/unit1308.c

index 49e7954..5419371 100644 (file)
@@ -891,7 +891,7 @@ int curl_formget(struct curl_httppost *form, void *arg,
           Curl_formclean(&data);
           return -1;
         }
-      } while(nread == sizeof(buffer));
+      } while(nread);
     }
     else {
       if(ptr->length != append(arg, ptr->line, ptr->length)) {
@@ -1306,6 +1306,11 @@ static size_t readfromfile(struct Form *form, char *buffer,
       return 0;
     else
       nread = form->fread_func(buffer, 1, size, form->data->line);
+
+    if(nread > size)
+      /* the read callback can return a value larger than the buffer but
+         treat any such as no data in this case */
+      nread = 0;
   }
   else {
     if(!form->fp) {
@@ -1316,9 +1321,9 @@ static size_t readfromfile(struct Form *form, char *buffer,
     }
     nread = fread(buffer, 1, size, form->fp);
   }
-  if(!nread || nread > size) {
+  if(!nread) {
     /* this is the last chunk from the file, move on */
-    if(!callback) {
+    if(form->fp) {
       fclose(form->fp);
       form->fp = NULL;
     }
index fe75096..88e9771 100644 (file)
@@ -23,6 +23,9 @@ formpost unit tests
 <tool>
 unit1308
 </tool>
+<file name="log/test-1308">
+Piece of the file that is to uploaded as a formpost
+</file>
 </client>
 
 </testcase>
index 6b2ab0d..80e6c57 100644 (file)
@@ -75,4 +75,21 @@ UNITTEST_START
 
   curl_formfree(post);
 
+  /* start a new formpost with a file upload and formget */
+  post = last = NULL;
+
+  rc = curl_formadd(&post, &last,
+                    CURLFORM_PTRNAME, "name of file field",
+                    CURLFORM_FILE, "log/test-1308",
+                    CURLFORM_FILENAME, "custom named file",
+                    CURLFORM_END);
+
+  fail_unless(rc == 0, "curl_formadd returned error");
+
+  rc = curl_formget(post, &total_size, print_httppost_callback);
+  fail_unless(rc == 0, "curl_formget returned error");
+  fail_unless(total_size == 847, "curl_formget got wrong size back");
+
+  curl_formfree(post);
+
 UNITTEST_STOP