]> granicus.if.org Git - curl/commitdiff
Dmitriy Sergeyev provided an example source code that crashed CVS libcurl
authorDaniel Stenberg <daniel@haxx.se>
Wed, 4 Oct 2006 21:11:08 +0000 (21:11 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 4 Oct 2006 21:11:08 +0000 (21:11 +0000)
but that worked nicely in 7.15.5. I converted it into test case 532 and
fixed the problem.

CHANGES
lib/easy.c
lib/multi.c
tests/data/Makefile.am
tests/data/test532 [new file with mode: 0644]
tests/libtest/Makefile.am
tests/libtest/lib526.c

diff --git a/CHANGES b/CHANGES
index c990c3cb4e577d229e18c61ace6d7a5571380673..3421f650185e8e8d0adc80acd05bc0140bb9feab 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@
 
                                   Changelog
 
+Daniel (4 October 2006)
+- Dmitriy Sergeyev provided an example source code that crashed CVS libcurl
+  but that worked nicely in 7.15.5. I converted it into test case 532 and
+  fixed the problem.
+
 Daniel (29 September 2006)
 - Removed a few other no-longer present options from the header file.
 
index 0d648064d3342f167734d31027d236769205a039..cd931b82cdb9e0175320157c4c871443d1eaa53f 100644 (file)
@@ -655,6 +655,12 @@ void curl_easy_reset(CURL *curl)
 {
   struct SessionHandle *data = (struct SessionHandle *)curl;
 
+  Curl_safefree(data->reqdata.pathbuffer);
+  data->reqdata.pathbuffer=NULL;
+
+  Curl_safefree(data->reqdata.proto.generic);
+  data->reqdata.proto.generic=NULL;
+
   /* zero out UserDefined data: */
   memset(&data->set, 0, sizeof(struct UserDefined));
 
index 9d596401a4e1def94c00fad524af89199132868b..46fd255f30432adeed7adff93d7c2ea531a905cd 100644 (file)
@@ -351,6 +351,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
 {
   struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
   struct Curl_one_easy *easy;
+  struct closure *cl;
+  struct closure *prev=NULL;
 
   /* First, make some basic checks that the CURLM handle is a good handle */
   if(!GOOD_MULTI_HANDLE(multi))
@@ -368,7 +370,21 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
   if(!easy)
     return CURLM_OUT_OF_MEMORY;
 
-  easy->numsocks=0;
+  cl = multi->closure;
+  while(cl) {
+    struct closure *next = cl->next;
+    if(cl->easy_handle == easy_handle) {
+      /* remove this handle from the closure list */
+      free(cl);
+      if(prev)
+        prev->next = next;
+      else
+        multi->closure = next;
+      break; /* no need to continue since this handle can only be present once
+                in the list */
+    }
+    cl = next;
+  }
 
   /* set the easy handle */
   easy->easy_handle = easy_handle;
@@ -1796,8 +1812,10 @@ static bool multi_conn_using(struct Curl_multi *multi,
   return FALSE;
 }
 
-/* add the given data pointer to the list of 'closure handles' that are
-   kept around only to be able to close some connections nicely */
+/* Add the given data pointer to the list of 'closure handles' that are kept
+   around only to be able to close some connections nicely - just make sure
+   that this handle isn't already added, like for the cases when an easy
+   handle is removed, added and removed again... */
 static void add_closure(struct Curl_multi *multi,
                         struct SessionHandle *data)
 {
index 0d0df9af0aa7bcff1f49d7f5b6f22e7ad692d9c4..51831ff2ba260efdcbe68900921ffa31933eecd0 100644 (file)
@@ -35,4 +35,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46           \
  test256 test257 test258 test259 test260 test261 test262 test263 test264   \
  test265 test266 test267 test268 test269 test270 test271 test272 test273   \
  test274 test275 test524 test525 test276 test277 test526 test527 test528   \
- test530 DISABLED test278 test279 test531 test280 test529
+ test530 DISABLED test278 test279 test531 test280 test529 test532
diff --git a/tests/data/test532 b/tests/data/test532
new file mode 100644 (file)
index 0000000..5421f81
--- /dev/null
@@ -0,0 +1,61 @@
+<info>
+<keywords>
+FTP
+PASV
+RETR
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+file contents should appear once for each file
+</data>
+<datacheck>
+file contents should appear once for each file
+file contents should appear once for each file
+file contents should appear once for each file
+file contents should appear once for each file
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+<tool>
+lib532
+</tool>
+ <name>
+FTP RETR same file using reset handles between each transfer
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/path/532
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+</strip>
+<protocol>
+USER anonymous\r
+PASS curl_by_daniel@haxx.se\r
+PWD\r
+CWD path\r
+EPSV\r
+TYPE I\r
+SIZE 532\r
+RETR 532\r
+EPSV\r
+SIZE 532\r
+RETR 532\r
+EPSV\r
+SIZE 532\r
+RETR 532\r
+EPSV\r
+SIZE 532\r
+RETR 532\r
+QUIT\r
+</protocol>
+</verify>
index 4b52a5f9afe051fb2039f37e6e5b1e78ca169b56..01b702015bead006821b8d629b799b36ff29ba7e 100644 (file)
@@ -42,7 +42,7 @@ SUPPORTFILES = first.c test.h
 noinst_PROGRAMS = lib500 lib501 lib502 lib503 lib504 lib505 lib506     \
   lib507 lib508 lib509 lib510 lib511 lib512 lib513 lib514 lib515 lib516        \
   lib517 lib518 lib519 lib520 lib521 lib523 lib524 lib525 lib526 lib527        \
-  lib529 lib530
+  lib529 lib530 lib532
 
 lib500_SOURCES = lib500.c $(SUPPORTFILES)
 lib500_LDADD = $(LIBDIR)/libcurl.la
@@ -145,6 +145,7 @@ lib525_LDADD = $(LIBDIR)/libcurl.la
 lib525_DEPENDENCIES = $(LIBDIR)/libcurl.la
 
 lib526_SOURCES = lib526.c $(SUPPORTFILES)
+lib526_CFLAGS = -DLIB526
 lib526_LDADD = $(LIBDIR)/libcurl.la
 lib526_DEPENDENCIES = $(LIBDIR)/libcurl.la
 
@@ -162,3 +163,8 @@ lib530_SOURCES = lib530.c $(SUPPORTFILES)
 lib530_CFLAGS = -DLIB530
 lib530_LDADD = $(LIBDIR)/libcurl.la
 lib530_DEPENDENCIES = $(LIBDIR)/libcurl.la
+
+lib532_SOURCES = lib526.c $(SUPPORTFILES)
+lib532_CFLAGS = -DLIB532
+lib532_LDADD = $(LIBDIR)/libcurl.la
+lib532_DEPENDENCIES = $(LIBDIR)/libcurl.la
index 04240808fa801b231c971ae9e1ff2b89f8d0e809..bf16c510ee6121195dee4d7a81fb700834cf24af 100644 (file)
  * sharing within the multi handle all transfers are performed on the same
  * persistent connection.
  *
- * This source code is used for lib526 _and_ lib527 with only #ifdefs
- * controlling the small differences. lib526 closes all easy handles after
- * they all have transfered the file over the single connection, while lib527
- * closes each easy handle after each single transfer. 526 and 527 use FTP,
- * while 528 uses the lib526 tool but use HTTP.
+ * This source code is used for lib526, lib527 and lib532 with only #ifdefs
+ * controlling the small differences.
+ *
+ * - lib526 closes all easy handles after
+ *   they all have transfered the file over the single connection
+ * - lib527 closes each easy handle after each single transfer.
+ * - lib532 uses only a single easy handle that is removed, reset and then
+ *   re-added for each transfer
+ *
+ * Test case 526, 527 and 532 use FTP, while test 528 uses the lib526 tool but
+ * with HTTP.
  */
 
 #include "test.h"
@@ -78,7 +84,21 @@ int test(char *URL)
 #endif
         if(++current < NUM_HANDLES) {
           fprintf(stderr, "Advancing to URL %d\n", current);
+#ifdef LIB532
+          /* first remove the only handle we use */
+          curl_multi_remove_handle(m, curl[0]);
+
+          /* make us re-use the same handle all the time, and try resetting
+             the handle first too */
+          curl_easy_reset(curl[0]);
+          curl_easy_setopt(curl[0], CURLOPT_URL, URL);
+          curl_easy_setopt(curl[0], CURLOPT_VERBOSE, 1);
+
+          /* re-add it */
+          res = (int)curl_multi_add_handle(m, curl[0]);
+#else
           res = (int)curl_multi_add_handle(m, curl[current]);
+#endif
           if(res) {
             fprintf(stderr, "add handle failed: %d.\n", res);
             res = 243;
@@ -121,7 +141,9 @@ int test(char *URL)
 #ifndef LIB527
   /* get NUM_HANDLES easy handles */
   for(i=0; i < NUM_HANDLES; i++) {
+#ifdef LIB526
     curl_multi_remove_handle(m, curl[i]);
+#endif
     curl_easy_cleanup(curl[i]);
   }
 #endif