From 552b963e6defebd6d0d6d41f8c74798d856c313c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 4 Oct 2006 21:11:08 +0000 Subject: [PATCH] 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. --- CHANGES | 5 ++++ lib/easy.c | 6 ++++ lib/multi.c | 24 +++++++++++++-- tests/data/Makefile.am | 2 +- tests/data/test532 | 61 +++++++++++++++++++++++++++++++++++++++ tests/libtest/Makefile.am | 8 ++++- tests/libtest/lib526.c | 32 ++++++++++++++++---- 7 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 tests/data/test532 diff --git a/CHANGES b/CHANGES index c990c3cb4e..3421f65018 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 0d648064d3..cd931b82cd 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 9d596401a4..46fd255f30 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 0d0df9af0a..51831ff2ba 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 0000000000..5421f81a7c --- /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 4b52a5f9af..01b702015b 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 04240808fa..bf16c510ee 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