From 4f84e6d9e249297fa659818d5e28934fc98c5936 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Apr 2004 07:52:39 +0000 Subject: [PATCH] removed the fixed dir depth limit in the FTP code --- CHANGES | 7 +++ RELEASE-NOTES | 1 + lib/ftp.c | 63 ++++++++++++--------- lib/urldata.h | 7 +-- tests/data/test142 | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 205 insertions(+), 36 deletions(-) diff --git a/CHANGES b/CHANGES index b802a61..7477dc4 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,13 @@ Changelog +Daniel (15 April 2004) +- Removed the fixed maximum amount of dir levels the FTP code supported. + Previously we had a fixed array for 100 levels, now we save space in each + handle by allocating only for a few level by default and then enlarging that + in case of need (with no maximum depth). Adjusted test case 142 to verify + that 150 dir levels work fine. + Daniel (14 April 2004) - Asking for CURL_IPRESOLVE_V6 when ipv6 addresses can't be resolved will now cause the resolve function to return NULL immediately. This flaw was diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 9caf178..e8914b2 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -7,6 +7,7 @@ Curl and libcurl 7.11.2. A bugfix release. This release includes the following changes: + o removed maximum dir depth limit in the FTP code o the ares build now requires c-ares 1.2.0 or later o --tcp-nodelay and CURLOPT_TCP_NODELAY were added o curl/curlver.h contains the libcurl version info now diff --git a/lib/ftp.c b/lib/ftp.c index d9028d4..7b942d8 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -124,9 +124,19 @@ static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path); static void freedirs(struct FTP *ftp) { int i; - for (i=0; ftp->dirs[i]; i++){ - free(ftp->dirs[i]); - ftp->dirs[i]=NULL; + if(ftp->dirs) { + for (i=0; i < ftp->dirdepth; i++){ + if(ftp->dirs[i]) { + free(ftp->dirs[i]); + ftp->dirs[i]=NULL; + } + } + free(ftp->dirs); + ftp->dirs = NULL; + } + if(ftp->file) { + free(ftp->file); + ftp->file = NULL; } } @@ -732,14 +742,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn) int ftpcode; CURLcode result=CURLE_OK; - /* free the dir tree parts */ + /* free the dir tree and file parts */ freedirs(ftp); - if(ftp->file) { - free(ftp->file); - ftp->file = NULL; - } - if(data->set.upload) { if((-1 != data->set.infilesize) && (data->set.infilesize != *ftp->bytecountp) && @@ -2317,7 +2322,6 @@ CURLcode Curl_ftp(struct connectdata *conn) char *slash_pos; /* position of the first '/' char in curpos */ char *cur_pos=conn->ppath; /* current position in ppath. point at the begin of next path component */ - int path_part=0;/* current path component */ /* the ftp struct is already inited in ftp_connect() */ ftp = conn->proto.ftp; @@ -2329,23 +2333,28 @@ CURLcode Curl_ftp(struct connectdata *conn) Curl_pgrsSetUploadSize(data, 0); Curl_pgrsSetDownloadSize(data, 0); - /* fixed : initialize ftp->dirs[xxx] to NULL ! - is done in Curl_ftp_connect() */ - + ftp->dirdepth = 0; + ftp->diralloc = 5; /* default dir depth to allocate */ + ftp->dirs = (char **)malloc(ftp->diralloc * sizeof(ftp->dirs[0])); + if(!ftp->dirs) + return CURLE_OUT_OF_MEMORY; + ftp->dirs[0] = NULL; /* to start with */ + /* parse the URL path into separate path components */ while((slash_pos=strchr(cur_pos, '/'))) { /* 1 or 0 to indicate absolute directory */ - bool absolute_dir = (cur_pos - conn->ppath > 0) && (path_part == 0); + bool absolute_dir = (cur_pos - conn->ppath > 0) && (ftp->dirdepth == 0); /* seek out the next path component */ if (slash_pos-cur_pos) { /* we skip empty path components, like "x//y" since the FTP command CWD requires a parameter and a non-existant parameter a) doesn't work on many servers and b) has no effect on the others. */ - ftp->dirs[path_part] = curl_unescape(cur_pos - absolute_dir, - slash_pos - cur_pos + absolute_dir); + ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir, + slash_pos - cur_pos + + absolute_dir); - if (!ftp->dirs[path_part]) { /* run out of memory ... */ + if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */ failf(data, "no memory"); freedirs(ftp); return CURLE_OUT_OF_MEMORY; @@ -2358,12 +2367,16 @@ CURLcode Curl_ftp(struct connectdata *conn) if(!retcode) { cur_pos = slash_pos + 1; /* jump to the rest of the string */ - if(++path_part >= (CURL_MAX_FTP_DIRDEPTH-1)) { - /* too deep, we need the last entry to be kept NULL at all - times to signal end of list */ - failf(data, "too deep dir hierarchy"); - freedirs(ftp); - return CURLE_URL_MALFORMAT; + if(++ftp->dirdepth >= ftp->diralloc) { + /* enlarge array */ + char *bigger; + ftp->diralloc *= 2; /* double the size each time */ + bigger = realloc(ftp->dirs, ftp->diralloc * sizeof(ftp->dirs[0])); + if(!bigger) { + freedirs(ftp); + return CURLE_OUT_OF_MEMORY; + } + ftp->dirs = (char **)bigger; } } } @@ -2511,10 +2524,6 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn) free(ftp->cache); ftp->cache = NULL; } - if(ftp->file) { - free(ftp->file); - ftp->file = NULL; /* zero */ - } freedirs(ftp); } return CURLE_OK; diff --git a/lib/urldata.h b/lib/urldata.h index f138fc4..1da8351 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -107,9 +107,6 @@ of need. */ #define HEADERSIZE 256 -/* Maximum number of dirs supported by libcurl in a FTP dir hierarchy */ -#define CURL_MAX_FTP_DIRDEPTH 100 - /* Just a convenience macro to get the larger value out of two given. We prefix with CURL to prevent name collisions. */ #define CURLMAX(x,y) ((x)>(y)?(x):(y)) @@ -244,7 +241,9 @@ struct FTP { char *user; /* user name string */ char *passwd; /* password string */ char *urlpath; /* the originally given path part of the URL */ - char *dirs[CURL_MAX_FTP_DIRDEPTH]; /* path components */ + char **dirs; /* realloc()ed array for path components */ + int dirdepth; /* number of entries used in the 'dirs' array */ + int diralloc; /* number of entries allocated for the 'dirs' array */ char *file; /* decoded file */ char *entrypath; /* the PWD reply when we logged on */ diff --git a/tests/data/test142 b/tests/data/test142 index b9470ab..b69550b 100644 --- a/tests/data/test142 +++ b/tests/data/test142 @@ -1,6 +1,7 @@ # Server-side +many parts there are @@ -10,21 +11,173 @@ ftp -FTP URL with too deep (100+) dir hierarchy +FTP URL with 150 dir levels -ftp://%HOSTIP:%FTPPORT/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/b +ftp://%HOSTIP:%FTPPORT/part1/part2/part3/part4/part5/part6/part7/part8/part9/part10/part11/part12/part13/part14/part15/part16/part17/part18/part19/part20/part21/part22/part23/part24/part25/part26/part27/part28/part29/part30/part31/part32/part33/part34/part35/part36/part37/part38/part39/part40/part41/part42/part43/part44/part45/part46/part47/part48/part49/part50/part51/part52/part53/part54/part55/part56/part57/part58/part59/part60/part61/part62/part63/part64/part65/part66/part67/part68/part69/part70/part71/part72/part73/part74/part75/part76/part77/part78/part79/part80/part81/part82/part83/part84/part85/part86/part87/part88/part89/part90/part91/part92/part93/part94/part95/part96/part97/part98/part99/part100/part101/part102/part103/part104/part105/part106/part107/part108/part109/part110/part111/part112/part113/part114/part115/part116/part117/part118/part119/part120/part121/part122/part123/part124/part125/part126/part127/part128/part129/part130/part131/part132/part133/part134/part135/part136/part137/part138/part139/part140/part141/part142/part143/part144/part145/part146/part147/part148/part149/part150/142 # Verify data after the test has been "shot" - -3 - USER anonymous PASS curl_by_daniel@haxx.se PWD +CWD part1 +CWD part2 +CWD part3 +CWD part4 +CWD part5 +CWD part6 +CWD part7 +CWD part8 +CWD part9 +CWD part10 +CWD part11 +CWD part12 +CWD part13 +CWD part14 +CWD part15 +CWD part16 +CWD part17 +CWD part18 +CWD part19 +CWD part20 +CWD part21 +CWD part22 +CWD part23 +CWD part24 +CWD part25 +CWD part26 +CWD part27 +CWD part28 +CWD part29 +CWD part30 +CWD part31 +CWD part32 +CWD part33 +CWD part34 +CWD part35 +CWD part36 +CWD part37 +CWD part38 +CWD part39 +CWD part40 +CWD part41 +CWD part42 +CWD part43 +CWD part44 +CWD part45 +CWD part46 +CWD part47 +CWD part48 +CWD part49 +CWD part50 +CWD part51 +CWD part52 +CWD part53 +CWD part54 +CWD part55 +CWD part56 +CWD part57 +CWD part58 +CWD part59 +CWD part60 +CWD part61 +CWD part62 +CWD part63 +CWD part64 +CWD part65 +CWD part66 +CWD part67 +CWD part68 +CWD part69 +CWD part70 +CWD part71 +CWD part72 +CWD part73 +CWD part74 +CWD part75 +CWD part76 +CWD part77 +CWD part78 +CWD part79 +CWD part80 +CWD part81 +CWD part82 +CWD part83 +CWD part84 +CWD part85 +CWD part86 +CWD part87 +CWD part88 +CWD part89 +CWD part90 +CWD part91 +CWD part92 +CWD part93 +CWD part94 +CWD part95 +CWD part96 +CWD part97 +CWD part98 +CWD part99 +CWD part100 +CWD part101 +CWD part102 +CWD part103 +CWD part104 +CWD part105 +CWD part106 +CWD part107 +CWD part108 +CWD part109 +CWD part110 +CWD part111 +CWD part112 +CWD part113 +CWD part114 +CWD part115 +CWD part116 +CWD part117 +CWD part118 +CWD part119 +CWD part120 +CWD part121 +CWD part122 +CWD part123 +CWD part124 +CWD part125 +CWD part126 +CWD part127 +CWD part128 +CWD part129 +CWD part130 +CWD part131 +CWD part132 +CWD part133 +CWD part134 +CWD part135 +CWD part136 +CWD part137 +CWD part138 +CWD part139 +CWD part140 +CWD part141 +CWD part142 +CWD part143 +CWD part144 +CWD part145 +CWD part146 +CWD part147 +CWD part148 +CWD part149 +CWD part150 +EPSV +TYPE I +SIZE 142 +RETR 142 +QUIT -- 2.7.4