cURL / Mailing Lists / curl-library / Single Mail

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

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 Simak
Received on 2006-12-08