Commit 119f4336 authored by Yang Tse's avatar Yang Tse
Browse files

allow write callbacks to indicate OOM to libcurl

Allow (*curl_write_callback) write callbacks to return
CURL_WRITEFUNC_OUT_OF_MEMORY to properly indicate libcurl of OOM conditions
inside the callback itself.
parent e276802f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -160,6 +160,11 @@ From 7.18.0, the function can return CURL_WRITEFUNC_PAUSE which then will
cause writing to this connection to become paused. See
\fIcurl_easy_pause(3)\fP for further details.

From 7.22.1, the function can return CURL_WRITEFUNC_OUT_OF_MEMORY to indicate
libcurl that an attempt to dynamically allocate memory from within the write
callback itself has failed. This will abort the transfer and make libcurl
return CURLE_OUT_OF_MEMORY.

This function may be called with zero bytes data if the transferred file is
empty.

+1 −0
Original line number Diff line number Diff line
@@ -685,4 +685,5 @@ CURL_VERSION_SPNEGO 7.10.8
CURL_VERSION_SSL                7.10
CURL_VERSION_SSPI               7.13.2
CURL_VERSION_TLSAUTH_SRP        7.21.4
CURL_WRITEFUNC_OUT_OF_MEMORY    7.22.1
CURL_WRITEFUNC_PAUSE            7.18.0
+6 −1
Original line number Diff line number Diff line
@@ -187,10 +187,15 @@ typedef int (*curl_progress_callback)(void *clientp,
#define CURL_MAX_HTTP_HEADER (100*1024)
#endif


/* This is a magic return code for the write callback that, when returned,
   will signal libcurl to pause receiving on the current transfer. */
#define CURL_WRITEFUNC_PAUSE 0x10000001

/* If the write callback itself allocates memory dynamically and this fails
   due to an out of memory condition, returning CURL_WRITEFUNC_OUT_OF_MEMORY
   is the proper way to tell libcurl of this condition. */
#define CURL_WRITEFUNC_OUT_OF_MEMORY 0x10000002

typedef size_t (*curl_write_callback)(char *buffer,
                                      size_t size,
                                      size_t nitems,
+12 −3
Original line number Diff line number Diff line
@@ -354,6 +354,8 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
  return CURLE_OK;
}

/* Curl_ftp_parselist is a write callback function */

size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
                          void *connptr)
{
@@ -365,6 +367,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
  unsigned long i = 0;
  CURLcode rc;

  if(bufflen >= CURL_WRITEFUNC_PAUSE)
    /* CURL_WRITEFUNC_PAUSE limits input size */
    return CURL_WRITEFUNC_OUT_OF_MEMORY;

  if(parser->error) { /* error in previous call */
    /* scenario:
     * 1. call => OK..
@@ -372,6 +378,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
     * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
     *    in wc_statemach()
     */
    if(parser->error == CURLE_OUT_OF_MEMORY)
      return CURL_WRITEFUNC_OUT_OF_MEMORY;

    return bufflen;
  }

@@ -388,12 +397,12 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
      parser->file_data = Curl_fileinfo_alloc();
      if(!parser->file_data) {
        parser->error = CURLE_OUT_OF_MEMORY;
        return bufflen;
        return CURL_WRITEFUNC_OUT_OF_MEMORY;
      }
      parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
      if(!parser->file_data->b_data) {
        PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
        return bufflen;
        return CURL_WRITEFUNC_OUT_OF_MEMORY;
      }
      parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
      parser->item_offset = 0;
@@ -416,7 +425,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
        parser->file_data = NULL;
        parser->error = CURLE_OUT_OF_MEMORY;
        PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
        return bufflen;
        return CURL_WRITEFUNC_OUT_OF_MEMORY;
      }
    }

+5 −0
Original line number Diff line number Diff line
@@ -725,6 +725,11 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
  writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
  wrote = writeit(ptr, 1, len, data->set.rtp_out);

  if(CURL_WRITEFUNC_OUT_OF_MEMORY == wrote) {
    failf (data, "Out of memory writing RTP data");
    return CURLE_OUT_OF_MEMORY;
  }

  if(CURL_WRITEFUNC_PAUSE == wrote) {
    failf (data, "Cannot pause RTP");
    return CURLE_WRITE_ERROR;
Loading