cURL / Mailing Lists / curl-library / Single Mail

curl-library

libCurl curl-7.36.0 crash in quote command - illegal access ftp.c - line - 1743

From: John Coffey <johnco3_at_gmail.com>
Date: Mon, 28 Apr 2014 12:14:30 -0400

I have some additional specific crash details from a post I made this
weekend (which I include for context below). The specific piece of code
where libCurl breaks is from the backtrace from curl_easy_perform which
breaks in the above line number (the function ftp_state_quote(...)).

Visual Studio 2013 indicates:

Unhandled exception at 0x000007FEF084A705 (libcurl.dll) in dlf.exe:
0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

static CURLcode ftp_state_quote(struct connectdata *conn,bool init,ftpstate
instate)

The arguments are conn points to what looks like a valid connectdata
structure, init = true & instate = FTPQUOTE (12),

item = data->set.quote points to struct containing 2 fields (data & next)
which are both NULL which is why the code below segfaults

    if(item) {
      char *cmd = item->data; <<<<< BLOWS UP HERE
      if(cmd[0] == '*') {
        cmd++;
        ftpc->count2 = 1; /* the sent command is allowed to fail */
      }

The problem occurs as after the second quote below - as you can see from
the attached wireshark screenshot, this causes the server to reboot
ungracefully - something over which I have no control).

Since my original post I also hooked into socked option callback - changing
the SO_LINGER to the following - I thought it might close the connection
more gracefully - not alas this was not the case. You will see various
lines interleaved with the libcurl verbose output below in upper case below
- this is printed as I run various scripts and it not something that curl
prints.

SETCNTX IP_ADDR 192.168.1.1|FTPLOGIN|

* Rebuilt URL to: ftp://192.168.1.1/
* timeout on name lookup is not supported
* Hostname was NOT found in DNS cache
* Trying 192.168.1.1...
* Connected to 192.168.1.1 (192.168.1.1) port 21 (#0)
< 220 FTP server ready, Epic file system aware.
> USER anonymous
< 331 User allowed.
> PASS ftp_at_example.com
< 230-Welcome!
< File uploading is DISABLED.
< Buffer will be interpreted as a FILE.
< Buffer is at 80000000 (HEX).
< The current list mode is UNIX.
< Persistent Storage remaining is 24825856 bytes.
< Persistent Storage yet to be reclaimed is 98304 bytes.
< The maximum number of files that can be stored is 409.
< The current number of stored files is 57.
< The kernel file system maximum filename length is 64.
< The epic file system maximum filename length is 127 (/LOCAL).
< The epic file system maximum filename length is 32 (/EEPROM).
< This server has a hard coded limit of 256 character bytes per filename.
< Since this server's maximum filename length exceeds the file systems',
all filenames will be accurate.
< hw-descriptor:p7038231-1902^:mA-E^:uBASET^
< 230
> PWD
< 257 "/" is current directory.
* Entry path is '/'
* ftp_perform ends with SECONDARY: 0
* Remembering we are in dir ""
* Connection #0 to host 192.168.1.1 left intact

SETCNTX RESP_OFF|FTPQUOTE "SITE IDLE"|

* Found bundle for host 192.168.1.1: 0x3c7c10
* Re-using existing connection! (#0) with host 192.168.1.1
* Connected to 192.168.1.1 (192.168.1.1) port 21 (#0)
* Request has same path as previous transfer
> SITE IDLE
* ftp_perform ends with SECONDARY: 0
< 501-Possible SITE commands are:
< ATTRIB - Change Kernel Attributes.
< APPLET - Upload is a binary applet.
< 501 NRBINFO - Display the NRB1 image information.
* QUOT command failed with 501
* Closing connection 0

FTPQUOTE "SITE ATTRIB 3"|

* timeout on name lookup is not supported
* Hostname was found in DNS cache
* Trying 192.168.1.1...
* Connected to 192.168.1.1 (192.168.1.1) port 21 (#1)
< 220 FTP server ready, Epic file system aware.
> USER anonymous
< 331 User allowed.
> PASS ftp_at_example.com
< 230-Welcome!
< File uploading is DISABLED.
< Buffer will be interpreted as a FILE.
< 230
> PWD
< 257 "/" is current directory.
* Entry path is '/'
> SITE ATTRIB 3
* ftp_perform ends with SECONDARY: 0
* Recv failure: Connection was reset
* Closing connection 1

SETCNTX IP_ADDR 192.168.1.1|FTPLOGIN|

* Rebuilt URL to: ftp://192.168.1.1/
* timeout on name lookup is not supported
* Hostname was found in DNS cache
* Trying 192.168.1.1...
* Connected to 192.168.1.1 (192.168.1.1) port 21 (#2)
< 220 FTP server ready, APM file system aware.
> USER anonymous
< 331 User allowed.
> PASS ftp_at_example.com
< 230-Welcome!
< File uploading is DISABLED.
< Buffer will be interpreted as a FILE.
< 230
> PWD
< 257 "/" is current directory.
* Entry path is '/'

[image: Inline image 1]

expanding on some of the TCP packets - showing the RST we have the following

[image: Inline image 2]

This is my original post:

Hello,

this is my first posting to the curl-library mailing list. I believe that
I may have discovered a new bug in libCurl 7.36 and hopefully here is the
place to ask for either a workaround or a solution. I am running on
windows 8.1 and I built libCurl x64 using Visual Studio 2013 and CMake
2.8.12.2 using the following to generate the makefile.

cmake -G "Visual Studio 12 Win64”

I am writing a high level scripting engine that communicates with an
embedded FTP server. The remote FTP server has several modes of operation
(download mode, upload mode kernel mode etc) that are changed through a
special 'site' command sequence sent to the server. I send these using
the curl_easy_setopt(curl, CURLOPT_QUOTE, slist);

The problem is that these servers can do one of 3 things in response to a
QUOTE SITE XXX command

(1) return a 500 error code indicating that the SITE XXX command failed -
libCurl then uncleanly severs the connection - (without sending a QUIT).
 Typically the ftp server (like tnftpd on a mac) will indicated “you might
have said goodbye” in the subsequent packet.

(2) with a successful error code (1XX/2XX) lib curl leaves the connection
open and subsequent ftp operations executed with curl_easy_perform progress
normally.

(3) with an immediate RST packet from the ftp server (effectively resulting
from a connection reset by peer) - this happens because the server reboots
to the requested mode specified in the SITE command without sending a 200
or other type of successful acknowledgement of the request.

Case 3 above is the cause of the creashes in libCurl I am encountering when
I attempt to use the (just closed without notification) connection the for
a subsequent SITE XXX or other command - even listing a directory - (the
idea is that these site commands are run back to back (it is a script
engine)). LibCurl crashes somewhere in ftp.c (I will have access to the
system where I can reproduce the problem on Monday and will add more
details then). If meanwhile there is something obvious wrong or if this is
a known bug - from a search I cannot see it to be so -

The code below shows how I initialize the curl easy options - I have set
the verbose flag on and I can see that curl does its best to always reuse
connections. Is there any way to know when a remote peer sends a RST
packet to sever the connection? My initial thought there may be some
socket callback mechanism to do that, however I am a newbie at libCurl.

Any help would be much appreciated

John

/**
 * Sets the curl options using the current mContextInfo.
 *
 * This never sets the URI curl field as this must be
 * done outside the context object.
 */
void
SLDBContext::setCurlOptions() {
    CURL* pCurl = mCurlHandle.get();
    // reset all curl context info
    curl_easy_reset(pCurl);
    // remoote server does not support EPSV or EPRT
    auto res = curl_easy_setopt(pCurl, CURLOPT_FTP_USE_EPSV, 0L);
    res = curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L);
    res = curl_easy_setopt(pCurl, CURLOPT_FTP_USE_EPRT, 0L);
    // do not perform CWD when traversing the pseudo directories
    res = curl_easy_setopt(pCurl, CURLOPT_FTP_FILEMETHOD,
CURLFTPMETHOD_NOCWD);
    res = curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT,
getConnectTimeoutSecs());
    if (!isPASVMode()) {
        res = curl_easy_setopt(pCurl, CURLOPT_FTPPORT, "-");
    }
    if (mHeaderCallback) {
        res = curl_easy_setopt(pCurl, CURLOPT_WRITEHEADER, &mHeaderStream);
        res = curl_easy_setopt(pCurl, CURLOPT_HEADERFUNCTION,
mHeaderCallback);
    }
    if (mWriteDataCallback) {
        res = curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, mMemBuffer.get());
        res = curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION,
mWriteDataCallback);
    }
}

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

image.png image.png
Received on 2014-04-28