Storage leak in ftp.c.
Tested against 7.11.1, using libcurl in Windows.
Submitted by mbp
at cadalog hyphen inc dot com.
In ftp.c, the lines 2400-2405 are:
else
freedirs(ftp);
ftp->ctl_valid = TRUE;
return retcode;
}
They should be:
else {
freedirs(ftp);
if(ftp->file) {
free(ftp->file);
ftp->file = NULL;
}
}
ftp->ctl_valid = TRUE;
return retcode;
}
If you check the mtime of a file on a FTP server, and the
file does not exist (and the FTP server does exist), then
ftp->file is not freed.
example code:
curl_easy_setopt(m_curlHandle, CURLOPT_URL, "ftp:
//xxx.yyy/zzz");
curl_easy_setopt(m_curlHandle, CURLOPT_FILETIME,
1);
curl_easy_setopt(m_curlHandle, CURLOPT_NOBODY,
1);
int rc = curl_easy_perform(m_curlHandle);
Logged In: YES
user_id=1110
How can you tell this is a leak?
I added a test case (511) that uses these libcurl options
and that does this operation on a missing file on an
existing FTP server. It frees the used memory just fine.
The test program I used looks like this:
http://curl.haxx.se/lxr/source/tests/libtest/lib511.c
Logged In: YES
user_id=1021195
You wrote:
>How can you tell this is a leak?
Good question. I am using libcurl in a larger project compiled
with MSVC 6. The run-time system reports storage leaks
when a debug version of an application exits. I tracked it to
the code I mentioned originally.
The failing case is (of course) more complicated, and I may
have to build my own test case. First of all, I use the same
curl_handle more than once. In the case where it fails, I
check mtime for the same file twice, one right after another.
The first time, ftp->file is not freed. The second check, which
immediately follows, clobbers the contents of ftp->file at line
2367:
ftp->file = cur_pos; /* the rest is the file name */
I found this originally by generating an error if ftp->file was not
zero when line 2367 was executed.
My original example was too simple. This is a better synopsis
of the actual code:
(void *)apasswd);
curl_easy_setopt(m_curlHandle, CURLOPT_FILETIME, 1);
curl_easy_setopt(m_curlHandle, CURLOPT_NOBODY, 1);
&mtime);
}
NULL);
curl_easy_setopt(m_curlHandle, CURLOPT_FILETIME, 0);
curl_easy_setopt(m_curlHandle, CURLOPT_NOBODY, 0);
(void *)apasswd);
curl_easy_setopt(m_curlHandle, CURLOPT_FILETIME, 1);
curl_easy_setopt(m_curlHandle, CURLOPT_NOBODY, 1);
&mtime);
}
NULL);
curl_easy_setopt(m_curlHandle, CURLOPT_FILETIME, 0);
curl_easy_setopt(m_curlHandle, CURLOPT_NOBODY, 0);
The ftp->file value is clobbered during the second
curl_easy_perform call.
I will try to create a small test case that repeats this
behavior.
But you can also examine the code and see that this is a
problem, even without a test case. In the Curl_ftp function,
both ftp->dirs[] and ftp->file are set to allocated strings. In
the error handling at the very end of the function, the strings
in ftp->dirs[] are freed, but not ftp->file.
Logged In: YES
user_id=1110
I replied to this in a mail and I cc'ed the libcurl mailing
list.
Logged In: YES
user_id=1110
No response and not able to repeat.