From 0e5da5b8bc8861f4c21521d154c4ef5d3cd96609 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 7 Jul 2008 20:37:07 +0000 Subject: [PATCH] - Scott Barrett provided a test case for a segfault in the FTP code and the fix for it. It occured when you did a FTP transfer using CURLFTPMETHOD_SINGLECWD and then did another one on the same easy handle but switched to CURLFTPMETHOD_NOCWD. Due to the "dir depth" variable not being cleared properly. Scott's test case is now known as test 539 and it verifies the fix. --- CHANGES | 8 +++++ RELEASE-NOTES | 3 +- lib/ftp.c | 1 + tests/data/test539 | 63 +++++++++++++++++++++++++++++++++++++ tests/libtest/Makefile.am | 5 ++- tests/libtest/lib539.c | 65 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 tests/data/test539 create mode 100644 tests/libtest/lib539.c diff --git a/CHANGES b/CHANGES index ddd020dc7..974a07b99 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,14 @@ Changelog +Daniel Stenberg (7 Jul 2008) +- Scott Barrett provided a test case for a segfault in the FTP code and the + fix for it. It occured when you did a FTP transfer using + CURLFTPMETHOD_SINGLECWD and then did another one on the same easy handle but + switched to CURLFTPMETHOD_NOCWD. Due to the "dir depth" variable not being + cleared properly. Scott's test case is now known as test 539 and it + verifies the fix. + Daniel Stenberg (3 Jul 2008) - Phil Blundell provided a fix for libcurl's treatment of unexpected 1xx response codes. Previously libcurl would hang on such occurances. I added diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 37c990ffb..32119ecba 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -30,6 +30,7 @@ This release includes the following bugfixes: o fallback to gettimeofday when monotonic clock is unavailable at run-time o range numbers could be made to wrongly get output as signed o unexpected 1xx responses hung transfers + o FTP transfers segfault when using different CURLOPT_FTP_FILEMETHOD This release includes the following known bugs: @@ -49,7 +50,7 @@ advice from friends like these: Lenny Rachitsky, Axel Tillequin, Arnaud Ebalard, Yang Tse, Dan Fandrich, Rob Crittenden, Dengminwen, Christopher Palow, Hans-Jurgen May, Phil Pellouchoud, Eduard Bloch, John Lightsey, Stephen Collyer, Tor Arntsen, - Rolland Dudemaine, Phil Blundell + Rolland Dudemaine, Phil Blundell, Scott Barrett Thanks! (and sorry if I forgot to mention someone) diff --git a/lib/ftp.c b/lib/ftp.c index ba24376fe..819772b92 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -279,6 +279,7 @@ static void freedirs(struct ftp_conn *ftpc) } free(ftpc->dirs); ftpc->dirs = NULL; + ftpc->dirdepth = 0; } if(ftpc->file) { free(ftpc->file); diff --git a/tests/data/test539 b/tests/data/test539 new file mode 100644 index 000000000..f1ad70107 --- /dev/null +++ b/tests/data/test539 @@ -0,0 +1,63 @@ + +# +# Server-side + + +file contents + + + +file contents +total 20 +drwxr-xr-x 8 98 98 512 Oct 22 13:06 . +drwxr-xr-x 8 98 98 512 Oct 22 13:06 .. +drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT +-r--r--r-- 1 0 1 35 Jul 16 1996 README +lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin +dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev +drwxrwxrwx 2 98 98 512 May 29 16:04 download.html +dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc +drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub +dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr + + + +# Client-side + + +ftp + +# tool is what to use instead of 'curl' + +lib539 + + + +Two FTP fetches using different CURLOPT_FTP_FILEMETHOD + + +ftp://%HOSTIP:%FTPPORT/path/to/the/file/539 + + + +# +# Verify data after the test has been "shot" + + +USER anonymous +PASS ftp@example.com +PWD +CWD path/to/the/file +EPSV +TYPE I +SIZE 539 +RETR 539 +SYST +CWD /nowhere/anywhere +EPSV +TYPE A +LIST path/to/the/file/539./ +QUIT + + + diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am index ff4532c9c..52e49b944 100644 --- a/tests/libtest/Makefile.am +++ b/tests/libtest/Makefile.am @@ -48,7 +48,8 @@ noinst_PROGRAMS = lib500 lib501 lib502 lib503 lib504 lib505 lib506 \ lib507 lib508 lib510 lib511 lib512 lib513 lib514 lib515 lib516 \ lib517 lib518 lib519 lib520 lib521 lib523 lib524 lib525 lib526 lib527 \ lib529 lib530 lib532 lib533 lib536 lib537 lib540 lib541 lib542 lib543 \ - lib544 lib545 lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 + lib544 lib545 lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 \ + lib539 # Dependencies (may need to be overriden) LDADD = $(LIBDIR)/libcurl.la @@ -124,6 +125,8 @@ lib536_SOURCES = lib536.c $(SUPPORTFILES) $(TESTUTIL) lib537_SOURCES = lib537.c $(SUPPORTFILES) +lib539_SOURCES = lib539.c $(SUPPORTFILES) + lib540_SOURCES = lib540.c $(SUPPORTFILES) lib541_SOURCES = lib541.c $(SUPPORTFILES) diff --git a/tests/libtest/lib539.c b/tests/libtest/lib539.c new file mode 100644 index 000000000..0e43654ef --- /dev/null +++ b/tests/libtest/lib539.c @@ -0,0 +1,65 @@ +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * $Id$ + */ + +#include "test.h" + +int test(char *URL) +{ + CURLcode res; + CURL *curl; + char *newURL; + struct curl_slist *slist; + + if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + fprintf(stderr, "curl_global_init() failed\n"); + return TEST_ERR_MAJOR_BAD; + } + + if ((curl = curl_easy_init()) == NULL) { + fprintf(stderr, "curl_easy_init() failed\n"); + curl_global_cleanup(); + return TEST_ERR_MAJOR_BAD; + } + + /* + * Begin with cURL set to use a single CWD to the URL's directory. + */ + curl_easy_setopt(curl, CURLOPT_URL, URL); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_SINGLECWD); + + res = curl_easy_perform(curl); + + /* + * Change the FTP_FILEMETHOD option to use full paths rather than a CWD + * command. Alter the URL's path a bit, appending a "./". Use an innocuous + * QUOTE command, after which cURL will CWD to ftp_conn->entrypath and then + * (on the next call to ftp_statemach_act) find a non-zero ftpconn->dirdepth + * even though no directories are stored in the ftpconn->dirs array (after a + * call to freedirs). + */ + newURL = strcat (strcpy ((char*)malloc (strlen (URL) + 3), + URL), + "./"); + slist = curl_slist_append (NULL, "SYST"); + + curl_easy_setopt(curl, CURLOPT_URL, newURL); + curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_NOCWD); + curl_easy_setopt(curl, CURLOPT_QUOTE, slist); + + res = curl_easy_perform(curl); + + curl_slist_free_all(slist); + free(newURL); + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return (int)res; +}