diff --git a/CHANGES b/CHANGES
index c990c3cb4..3421f6501 100644
--- 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.
diff --git a/lib/easy.c b/lib/easy.c
index 0d648064d..cd931b82c 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -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));
diff --git a/lib/multi.c b/lib/multi.c
index 9d596401a..46fd255f3 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -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)
{
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 0d0df9af0..51831ff2b 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -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
index 000000000..5421f81a7
--- /dev/null
+++ b/tests/data/test532
@@ -0,0 +1,61 @@
+
+
+FTP
+PASV
+RETR
+
+
+# Server-side
+
+
+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
+file contents should appear once for each file
+
+
+
+# Client-side
+
+
+ftp
+
+
+lib532
+
+
+FTP RETR same file using reset handles between each transfer
+
+
+ftp://%HOSTIP:%FTPPORT/path/532
+
+
+
+# Verify data after the test has been "shot"
+
+
+
+
+USER anonymous
+PASS curl_by_daniel@haxx.se
+PWD
+CWD path
+EPSV
+TYPE I
+SIZE 532
+RETR 532
+EPSV
+SIZE 532
+RETR 532
+EPSV
+SIZE 532
+RETR 532
+EPSV
+SIZE 532
+RETR 532
+QUIT
+
+
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 4b52a5f9a..01b702015 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -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
diff --git a/tests/libtest/lib526.c b/tests/libtest/lib526.c
index 04240808f..bf16c510e 100644
--- a/tests/libtest/lib526.c
+++ b/tests/libtest/lib526.c
@@ -14,11 +14,17 @@
* 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