curl-library
Memory leak if FTP server responds "530 Login incorrect"
From: Alexey Simak <alexeysimak_at_gmail.com>
Date: Fri, 8 Dec 2006 17:16:28 +0200
Date: Fri, 8 Dec 2006 17:16:28 +0200
Hi,
struct connectdata allocated in url.c, line 2720 is not
destroyed if multi interface is used and FTP server
responds "530 Login incorrect".
libcurl version: 7.16.0
OS: Microsoft Windows Server 2003, Enterprise Edition, SP1, v1039.
Compiler: MS Visual C++ 6.0
FTP server: IIS 6.0
Here is a simple program to reproduce the problem:
//--------------------------------------------------------------------------
--- #include "curl.h" struct FtpFile { char *filename; FILE *stream; }; int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out=(struct FtpFile *)stream; if(out && !out->stream) { /* open file for writing */ out->stream=fopen(out->filename, "wb"); if(!out->stream) return -1; /* failure, can't open file to write */ } return fwrite(buffer, size, nmemb, out->stream); } int main(int argc, char* argv[]) { CURL* handle; CURLM* multi_handle; int still_running; /* keep number of running handles */ struct FtpFile ftpfile={ "test.txt", /* name to store the file as if succesful */ NULL }; curl_global_init(CURL_GLOBAL_DEFAULT); multi_handle = curl_multi_init(); handle = curl_easy_init(); CURLMcode code = curl_multi_add_handle( multi_handle, handle ); curl_easy_setopt(handle, CURLOPT_URL, "ftp://ftp.univ.kiev.ua/pub/incoming/test.txt"); /* Define our callback to get called when there's data to be written */ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_fwrite); /* Set a pointer to our struct to pass to the callback */ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &ftpfile); /* Switch on full protocol/debug output */ curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); // Make FTP server respond 503 curl_easy_setopt( handle, CURLOPT_USERPWD, "invaliduser:invalidpwd" ); /* we start some action by calling perform right away */ while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running)); while(still_running) { struct timeval timeout; int rc; /* select() return code */ fd_set fdread; fd_set fdwrite; fd_set fdexcep; int maxfd; FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); /* set a suitable timeout to play around with */ timeout.tv_sec = 1; timeout.tv_usec = 0; /* get file descriptors from the transfers */ curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); /* In a real-world program you OF COURSE check the return code of the function calls, *and* you make sure that maxfd is bigger than -1 so that the call to select() below makes sense! */ rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); switch(rc) { case -1: /* select error */ still_running = 0; printf("select() returns error, this is badness\n"); break; case 0: default: /* timeout or readable/writable sockets */ while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &still_running)); break; } } curl_multi_remove_handle( multi_handle, handle ); curl_easy_cleanup( handle ); curl_multi_cleanup( multi_handle ); if(ftpfile.stream) fclose(ftpfile.stream); /* close the local file */ curl_global_cleanup(); return 0; } //-------------------------------------------------------------------------- --- Best regards, Alexey SimakReceived on 2006-12-08