- Scott Barrett provided a test case for a segfault in the FTP code and the
authorDaniel Stenberg <daniel@haxx.se>
Mon, 7 Jul 2008 20:37:07 +0000 (20:37 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 7 Jul 2008 20:37:07 +0000 (20:37 +0000)
  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
RELEASE-NOTES
lib/ftp.c
tests/data/test539 [new file with mode: 0644]
tests/libtest/Makefile.am
tests/libtest/lib539.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index ddd020d..974a07b 100644 (file)
--- 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
index 37c990f..32119ec 100644 (file)
@@ -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)
index ba24376..819772b 100644 (file)
--- 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 (file)
index 0000000..f1ad701
--- /dev/null
@@ -0,0 +1,63 @@
+<testcase>
+#
+# Server-side
+<reply>
+<data mode="text">
+file contents
+</data>
+
+<datacheck>
+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
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib539
+</tool>
+
+ <name>
+Two FTP fetches using different CURLOPT_FTP_FILEMETHOD
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/path/to/the/file/539
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous\r
+PASS ftp@example.com\r
+PWD\r
+CWD path/to/the/file\r
+EPSV\r
+TYPE I\r
+SIZE 539\r
+RETR 539\r
+SYST\r
+CWD /nowhere/anywhere\r
+EPSV\r
+TYPE A\r
+LIST path/to/the/file/539./\r
+QUIT\r
+</protocol>
+</verify>
+</testcase>
index ff4532c..52e49b9 100644 (file)
@@ -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 (file)
index 0000000..0e43654
--- /dev/null
@@ -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;
+}