Commit 081e2893 authored by Yang Tse's avatar Yang Tse
Browse files

curl tool: fix some OOM handling issues

parent 5f076487
Loading
Loading
Loading
Loading
+207 −169
Original line number Diff line number Diff line
@@ -3408,8 +3408,8 @@ int my_trace(CURL *handle, curl_infotype type,
  return 0;
}

#define RETRY_SLEEP_DEFAULT 1000  /* ms */
#define RETRY_SLEEP_MAX     600000 /* ms == 10 minutes */
#define RETRY_SLEEP_DEFAULT 1000L   /* ms */
#define RETRY_SLEEP_MAX     600000L /* ms == 10 minutes */

static bool
output_expected(const char* url, const char* uploadfile)
@@ -3684,66 +3684,57 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
  char errorbuffer[CURL_ERROR_SIZE];
  struct ProgressData progressbar;
  struct getout *urlnode;
  struct getout *nextnode;

  struct OutStruct outs;
  struct OutStruct heads;
  struct InStruct input;

  URLGlob *urls=NULL;
  URLGlob *inglob=NULL;
  int urlnum;
  int infilenum;
  char *uploadfile=NULL; /* a single file, never a glob */

  curl_off_t uploadfilesize; /* -1 means unknown */
  bool stillflags=TRUE;

  CURL *curl = NULL;
  char *httpgetfields = NULL;

  CURL *curl;
  bool stillflags;
  int res = 0;
  int i;
  long retry_sleep_default;
  long retry_sleep;

  char *env;

  errorbuffer[0] = '\0';
  memset(&outs, 0, sizeof(struct OutStruct));
  memset(&heads, 0, sizeof(struct OutStruct));

  memory_tracking_init();

  /* Initialize curl library - do not call any libcurl functions before.
     Note that the memory_tracking_init() magic above is an exception, but
     then that's not part of the official public API.
  /*
  ** Initialize curl library - do not call any libcurl functions before
  ** this point. Note that the memory_tracking_init() magic above is an
  ** exception, but then that's not part of the official public API.
  */
  if(main_init() != CURLE_OK) {
    helpf(config->errors, "error initializing curl library\n");
    return CURLE_FAILED_INIT;
  }

  /*
   * Get a curl handle to use for all forthcoming curl transfers.  Cleanup
   * when all transfers are done.
   */
  /* Get libcurl info right away */
  if(get_libcurl_info() != CURLE_OK) {
    helpf(config->errors, "error retrieving curl library information\n");
    main_free();
    return CURLE_FAILED_INIT;
  }

  /* Get a curl handle to use for all forthcoming curl transfers */
  curl = curl_easy_init();
  if(!curl) {
    clean_getout(config);
    helpf(config->errors, "error initializing curl easy handle\n");
    main_free();
    return CURLE_FAILED_INIT;
  }
  config->easy = curl;

  memset(&outs,0,sizeof(outs));

  /* Store a pointer to our 'outs' struct used for output writing */
  config->outs = &outs;

  /* we get libcurl info right away */
  if(get_libcurl_info() != CURLE_OK) {
    clean_getout(config);
    return CURLE_FAILED_INIT;
  }

  errorbuffer[0]=0; /* prevent junk from being output */
  /*
  ** Beyond this point no return'ing from this function allowed.
  ** Jump to label 'quit_curl' in order to abandon this function
  ** from outside of nested loops further down below.
  */

  /* setup proper locale from environment */
#ifdef HAVE_SETLOCALE
@@ -3762,7 +3753,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
    CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
  config->proto_redir_present = FALSE;

  if(argc>1 &&
  if((argc > 1) &&
     (!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
     strchr(argv[1], 'q')) {
    /*
@@ -3777,11 +3768,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])

  if((argc < 2)  && !config->url_list) {
    helpf(config->errors, NULL);
    return CURLE_FAILED_INIT;
    res = CURLE_FAILED_INIT;
    goto quit_curl;
  }

  /* Parse options */
  for(i = 1; i < argc; i++) {
  for(i = 1, stillflags = TRUE; i < argc; i++) {
    if(stillflags &&
       ('-' == argv[i][0])) {
      char *nextarg;
@@ -3795,7 +3787,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
           following (URL) argument to start with -. */
        stillflags = FALSE;
      else {
        nextarg= (i < argc - 1)? argv[i+1]: NULL;
        nextarg = (i < (argc-1)) ? argv[i+1] : NULL;

        res = getparameter(flag, nextarg, &passarg, config);
        if(res) {
@@ -3805,8 +3797,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
            helpf(config->errors, "option %s: %s\n", origopt, reason);
            retval = CURLE_FAILED_INIT;
          }
          clean_getout(config);
          return retval;
          res = retval;
          goto quit_curl;
        }

        if(passarg) /* we're supposed to skip this */
@@ -3818,24 +3810,20 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
      /* just add the URL please */
      res = getparameter((char *)"--url", argv[i], &used, config);
      if(res)
        return res;
        goto quit_curl;
    }
  }

  retry_sleep_default = config->retry_delay?
    config->retry_delay*1000:RETRY_SLEEP_DEFAULT; /* ms */
  retry_sleep = retry_sleep_default;

  if((!config->url_list || !config->url_list->url) && !config->list_engines) {
    clean_getout(config);
    helpf(config->errors, "no URL specified!\n");
    return CURLE_FAILED_INIT;
    res = CURLE_FAILED_INIT;
    goto quit_curl;
  }

  if(!config->useragent)
    config->useragent = my_useragent();
  if(!config->useragent) {
    clean_getout(config);
    helpf(config->errors, "out of memory\n");
    res = CURLE_OUT_OF_MEMORY;
    goto quit_curl;
  }
@@ -3852,12 +3840,14 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
  if(!config->cacert &&
     !config->capath &&
     !config->insecure_ok) {
    char *env;
    env = curlx_getenv("CURL_CA_BUNDLE");
    if(env) {
      config->cacert = strdup(env);
      if(!config->cacert) {
        clean_getout(config);
        curl_free(env);
        helpf(config->errors, "out of memory\n");
        res = CURLE_OUT_OF_MEMORY;
        goto quit_curl;
      }
    }
@@ -3866,8 +3856,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
      if(env) {
        config->capath = strdup(env);
        if(!config->capath) {
          clean_getout(config);
          curl_free(env);
          helpf(config->errors, "out of memory\n");
          res = CURLE_OUT_OF_MEMORY;
          goto quit_curl;
        }
      }
@@ -3876,8 +3867,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        if(env) {
          config->cacert = strdup(env);
          if(!config->cacert) {
            clean_getout(config);
            curl_free(env);
            helpf(config->errors, "out of memory\n");
            res = CURLE_OUT_OF_MEMORY;
            goto quit_curl;
          }
        }
@@ -3889,11 +3881,9 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
#ifdef WIN32
    else {
      res = FindWin32CACert(config, "curl-ca-bundle.crt");
      if(res) {
        clean_getout(config);
      if(res)
        goto quit_curl;
    }
    }
#endif
  }

@@ -3905,27 +3895,28 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
      if(SetHTTPrequest(config,
                        (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
                        &config->httpreq)) {
        Curl_safefree(httpgetfields);
        return PARAM_BAD_USE;
        res = PARAM_BAD_USE;
        goto quit_curl;
      }
    }
    else {
      if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq))
        return PARAM_BAD_USE;
      if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
        res = PARAM_BAD_USE;
        goto quit_curl;
      }
    }
  }

  /* This is the first entry added to easysrc and it initializes the slist */
  easysrc = curl_slist_append(easysrc, "CURL *hnd = curl_easy_init();");
  if(!easysrc) {
    clean_getout(config);
    helpf(config->errors, "out of memory\n");
    res = CURLE_OUT_OF_MEMORY;
    goto quit_curl;
  }

  if(config->list_engines) {
    struct curl_slist *engines = NULL;

    curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
    list_engines(engines);
    curl_slist_free_all(engines);
@@ -3933,44 +3924,58 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
    goto quit_curl;
  }

  /* After this point, we should call curl_easy_cleanup() if we decide to bail
   * out from this function! */

  urlnode = config->url_list;

  /* Single header file for all URLs */
  if(config->headerfile) {
    /* open file for output: */
    if(strcmp(config->headerfile, "-")) {
      FILE *newfile = fopen(config->headerfile, "wb");
      if(!newfile) {
        warnf(config, "Failed to open %s\n", config->headerfile);
        res = CURLE_WRITE_ERROR;
        goto quit_curl;
      }
      else {
        heads.filename = config->headerfile;
        heads.alloc_filename = FALSE;
        heads.stream = newfile;
        heads.config = config;
      }
    else
    }
    else {
      heads.filename = config->headerfile; /* "-" */
      heads.alloc_filename = FALSE;
      heads.stream = stdout;
      heads.config = config;
    }
  }

  /*
  ** Nested loops start here.
  */

  /* loop through the list of given URLs */
  while(urlnode) {

  for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {

    int up; /* upload file counter within a single upload glob */
    char *dourl;
    char *url;
    char *infiles; /* might be a glob pattern */
    char *outfiles=NULL;
    char *outfiles;
    int infilenum;
    URLGlob *inglob;

    /* get the full URL (it might be NULL) */
    dourl=urlnode->url;
    outfiles = NULL;
    infilenum = 0;
    inglob = NULL;

    url = dourl;
    /* urlnode->url is the full URL (it might be NULL) */

    if(NULL == url) {
      /* This node had no URL, skip it and continue to the next */
    if(!urlnode->url) {
      /* This node has no URL. Free node data without destroying the
         node itself nor modifying next pointer and continue to next */
      Curl_safefree(urlnode->outfile);

      /* move on to the next URL */
      nextnode=urlnode->next;
      Curl_safefree(urlnode); /* free the node */
      urlnode = nextnode;
      continue; /* next please */
      Curl_safefree(urlnode->infile);
      urlnode->flags = 0;
      continue; /* next URL please */
    }

    /* default output stream is stdout */
@@ -3983,7 +3988,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
    if(urlnode->outfile) {
      outfiles = strdup(urlnode->outfile);
      if(!outfiles) {
        clean_getout(config);
        helpf(config->errors, "out of memory\n");
        res = CURLE_OUT_OF_MEMORY;
        break;
      }
    }
@@ -3994,8 +4000,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
      /* Unless explicitly shut off */
      res = glob_url(&inglob, infiles, &infilenum,
                     config->showerror?config->errors:NULL);
      if(res != CURLE_OK) {
        clean_getout(config);
      if(res) {
        Curl_safefree(outfiles);
        break;
      }
@@ -4005,8 +4010,15 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
       single globbed string. If no upload, we enter the loop once anyway. */
    for(up = 0 ;; up++) {

      long retry_numretries;
      char *uploadfile; /* a single file, never a glob */
      int separator;
      URLGlob *urls;
      int urlnum;

      uploadfile = NULL;
      separator = 0;
      urls = NULL;
      urlnum = 0;

      if(!up && !infiles)
        Curl_nop_stmt;
@@ -4021,15 +4033,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
          break;
      }

      separator = 0;
      uploadfilesize = -1;

      if(!config->globoff) {
        /* Unless explicitly shut off, we expand '{...}' and '[...]'
           expressions and return total number of URLs in pattern set */
        res = glob_url(&urls, dourl, &urlnum,
        res = glob_url(&urls, urlnode->url, &urlnum,
                       config->showerror?config->errors:NULL);
        if(res != CURLE_OK) {
        if(res) {
          Curl_safefree(uploadfile);
          break;
        }
      }
@@ -4045,19 +4055,27 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        int infd;
        bool infdopen;
        char *outfile;
        struct InStruct input;
        struct timeval retrystart;
        curl_off_t uploadfilesize;
        long retry_numretries;
        long retry_sleep_default;
        long retry_sleep;
        char *this_url;

        outfile = NULL;
        infdopen = FALSE;
        infd = STDIN_FILENO;
        uploadfilesize = -1; /* -1 means unknown */

        if(urls)
          url = glob_next_url(urls);
        else if(!i)
          url = strdup(url);
          this_url = glob_next_url(urls);
        else if(!i) {
          this_url = strdup(urlnode->url);
        }
        else
          url = NULL;
        if(!url)
          this_url = NULL;
        if(!this_url)
          break;

        if(outfiles) {
@@ -4078,7 +4096,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])

          if(!outfile) {
            /* extract the file name from the URL */
            outfile = get_url_file_name(url);
            outfile = get_url_file_name(this_url);
            if((!outfile || !*outfile) && !config->content_disposition) {
              helpf(config->errors, "Remote file name has no length!\n");
              res = CURLE_WRITE_ERROR;
@@ -4160,8 +4178,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
           */
          struct_stat fileinfo;

          url = add_file_name_to_url(curl, url, uploadfile);
          if(!url) {
          this_url = add_file_name_to_url(curl, this_url, uploadfile);
          if(!this_url) {
            res = CURLE_OUT_OF_MEMORY;
            goto show_error;
          }
@@ -4237,7 +4255,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        if(uploadfile && config->resume_from_current)
          config->resume_from = -1; /* -1 will then force get-it-yourself */

        if(output_expected(url, uploadfile)
        if(output_expected(this_url, uploadfile)
           && outs.stream && isatty(fileno(outs.stream)))
          /* we send the output to a tty, therefore we switch off the progress
             meter */
@@ -4245,19 +4263,19 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])

        if(urlnum > 1 && !(config->mute)) {
          fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
                  i+1, urlnum, url, outfile ? outfile : "<stdout>");
                  i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
          if(separator)
            printf("%s%s\n", CURLseparator, url);
            printf("%s%s\n", CURLseparator, this_url);
        }
        if(httpgetfields) {
          char *urlbuffer;
          /* Find out whether the url contains a file name */
          const char *pc = strstr(url, "://");
          const char *pc = strstr(this_url, "://");
          char sep = '?';
          if(pc)
            pc += 3;
          else
            pc = url;
            pc = this_url;

          pc = strrchr(pc, '/'); /* check for a slash */

@@ -4272,21 +4290,21 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
          /*
           * Then append ? followed by the get fields to the url.
           */
          urlbuffer = malloc(strlen(url) + strlen(httpgetfields) + 3);
          urlbuffer = malloc(strlen(this_url) + strlen(httpgetfields) + 3);
          if(!urlbuffer) {
            res = CURLE_OUT_OF_MEMORY;
            goto show_error;
          }
          if(pc)
            sprintf(urlbuffer, "%s%c%s", url, sep, httpgetfields);
            sprintf(urlbuffer, "%s%c%s", this_url, sep, httpgetfields);
          else
            /* Append  / before the ? to create a well-formed url
               if the url contains a hostname only
            */
            sprintf(urlbuffer, "%s/?%s", url, httpgetfields);
            sprintf(urlbuffer, "%s/?%s", this_url, httpgetfields);

          Curl_safefree(url); /* free previous URL */
          url = urlbuffer; /* use our new URL instead! */
          Curl_safefree(this_url); /* free previous URL */
          this_url = urlbuffer; /* use our new URL instead! */
        }

        if(!config->errors)
@@ -4312,7 +4330,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        my_setopt(curl, CURLOPT_READDATA, &input);
        /* what call to read */
        if((outfile && !curlx_strequal("-", outfile)) ||
           !checkprefix("telnet:", url))
           !checkprefix("telnet:", this_url))
          my_setopt(curl, CURLOPT_READFUNCTION, my_fread);

        /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
@@ -4328,7 +4346,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        /* size of uploaded file: */
        if(uploadfilesize != -1)
          my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
        my_setopt_str(curl, CURLOPT_URL, url);     /* what to fetch */
        my_setopt_str(curl, CURLOPT_URL, this_url);     /* what to fetch */
        my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
        if(config->no_body) {
          my_setopt(curl, CURLOPT_NOBODY, 1);
@@ -4741,8 +4759,12 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
          my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
                        config->gssapi_delegation);

        retry_numretries = config->req_retry;
        /* initialize retry vars for loop below */
        retry_sleep_default = (config->retry_delay) ?
          config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */

        retry_numretries = config->req_retry;
        retry_sleep = retry_sleep_default; /* ms */
        retrystart = cutil_tvnow();

        for(;;) {
@@ -4761,7 +4783,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
          if(retry_numretries &&
             (!config->retry_maxtime ||
              (cutil_tvdiff(cutil_tvnow(), retrystart)<
               config->retry_maxtime*1000)) ) {
               config->retry_maxtime*1000L)) ) {
            enum {
              RETRY_NO,
              RETRY_TIMEOUT,
@@ -4779,10 +4801,10 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
              /* If it returned OK. _or_ failonerror was enabled and it
                 returned due to such an error, check for HTTP transient
                 errors to retry on. */
              char *this_url=NULL;
              curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &this_url);
              if(this_url &&
                 checkprefix("http", this_url)) {
              char *effective_url = NULL;
              curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
              if(effective_url &&
                 checkprefix("http", effective_url)) {
                /* This was HTTP(S) */
                curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);

@@ -4825,7 +4847,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
              warnf(config, "Transient problem: %s "
                    "Will retry in %ld seconds. "
                    "%ld retries left.\n",
                    m[retry], retry_sleep/1000, retry_numretries);
                    m[retry], retry_sleep/1000L, retry_numretries);

              go_sleep(retry_sleep);
              retry_numretries--;
@@ -4870,7 +4892,6 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
          } /* if retry_numretries */

          /* In all ordinary cases, just break out of loop here */
          retry_sleep = retry_sleep_default;
          break; /* curl_easy_perform loop */

        }
@@ -4974,30 +4995,15 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
        }
#endif

        /* Cleanup loop-local variables for next loop iteration or exit */
        /* Free loop-local allocated memory and close loop-local opened fd */

        if(infdopen) {
          close(infd);
          infdopen = FALSE;    /* not needed */
          infd = STDIN_FILENO; /* not needed */
        }
        Curl_safefree(outfile);
        Curl_safefree(this_url);

        /* ... */

        Curl_safefree(url);

        if(res) {
          /* Free list of remaining URLs */
          if(urls) {
            glob_cleanup(urls);
            urls = NULL;
          }
          /* Free list of globbed upload files */
          if(inglob) {
            glob_cleanup(inglob);
            inglob = NULL;
          }
        if(infdopen) {
          close(infd);
          infdopen = FALSE;
          infd = STDIN_FILENO;
        }

        /* upon error exit loop */
@@ -5006,52 +5012,84 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])

      } /* loop to the next URL */

      /* Free loop-local allocated memory and close loop-local opened fd */

      Curl_safefree(uploadfile);

      if(urls) {
        /* cleanup memory used for URL globbing patterns */
        /* Free list of remaining URLs */
        glob_cleanup(urls);
        urls = NULL;
      }

      Curl_safefree(uploadfile);

      /* upon error exit loop */
      if(res)
        break;

    } /* loop to the next globbed upload file */

    /* Free loop-local allocated memory and close loop-local opened fd */

    Curl_safefree(outfiles);

    if(inglob) {
      /* Free list of globbed upload files */
      glob_cleanup(inglob);
      inglob = NULL;
    }

    Curl_safefree(outfiles);

    /* empty this urlnode struct */
    /* Free this URL node data without destroying the
       the node itself nor modifying next pointer. */
    Curl_safefree(urlnode->url);
    Curl_safefree(urlnode->outfile);
    Curl_safefree(urlnode->infile);
    urlnode->flags = 0;

    /* move on to the next URL */
    nextnode=urlnode->next;
    Curl_safefree(urlnode); /* free the node */
    urlnode = nextnode;
    /*
    ** Bail out upon critical errors
    */
    switch(res) {
    case CURLE_FAILED_INIT:
    case CURLE_OUT_OF_MEMORY:
    case CURLE_FUNCTION_NOT_FOUND:
    case CURLE_BAD_FUNCTION_ARGUMENT:
      goto quit_curl;
    default:
      /* Merrily loop to next URL */
      break;
    }

  } /* while-loop through all URLs */
  } /* for-loop through all URLs */

  /*
  ** Nested loops end here.
  */

  quit_curl:

  /* Free function-local referenced allocated memory */
  Curl_safefree(httpgetfields);

  Curl_safefree(config->engine);
  /* Free list of given URLs */
  clean_getout(config);

  /* cleanup the curl handle! */
  /* Cleanup the curl handle now that our
     progressbar struct is still in scope */
  if(curl) {
    curl_easy_cleanup(curl);
  config->easy = NULL; /* cleanup now */
    config->easy = curl = NULL;
  }
  if(easysrc)
    curl_slist_append(easysrc, "curl_easy_cleanup(hnd);");

  if(heads.stream && (heads.stream != stdout))
  /* Close function-local opened file descriptors */

  if(config->headerfile) {
    if(strcmp(heads.filename, "-") && heads.stream)
      fclose(heads.stream);
    if(heads.alloc_filename)
      Curl_safefree(heads.filename);
  }

  if(config->trace_fopened && config->trace_stream)
    fclose(config->trace_stream);
@@ -5061,7 +5099,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
     so not everything can be closed and cleaned before this is called */
  dumpeasysrc(config);

  if(config->errors_fopened)
  if(config->errors_fopened && config->errors)
    fclose(config->errors);

  main_free(); /* cleanup */
+19 −10
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@

void free_config_fields(struct Configurable *config)
{
  struct getout *urlnode;

  if(config->easy) {
    curl_easy_cleanup(config->easy);
    config->easy = NULL;
@@ -65,10 +67,19 @@ void free_config_fields(struct Configurable *config)

  Curl_safefree(config->netrc_file);

  /* config->url_list not handled */
  /* config->url_last not handled */
  /* config->url_get not handled */
  /* config->url_out not handled */
  urlnode = config->url_list;
  while(urlnode) {
    struct getout *next = urlnode->next;
    Curl_safefree(urlnode->url);
    Curl_safefree(urlnode->outfile);
    Curl_safefree(urlnode->infile);
    Curl_safefree(urlnode);
    urlnode = next;
  }
  config->url_list = NULL;
  config->url_last = NULL;
  config->url_get = NULL;
  config->url_out = NULL;

  Curl_safefree(config->cipher_list);
  Curl_safefree(config->cert);
@@ -81,18 +92,17 @@ void free_config_fields(struct Configurable *config)
  Curl_safefree(config->key_passwd);
  Curl_safefree(config->pubkey);
  Curl_safefree(config->hostpubmd5);

  /* config->engine not handled */
  Curl_safefree(config->engine);

  Curl_safefree(config->customrequest);
  Curl_safefree(config->krblevel);
  Curl_safefree(config->trace_dump);

  /* config->trace_stream not handled */
  config->trace_stream = NULL; /* closed elsewhere when appropriate */

  Curl_safefree(config->writeout);

  /* config->errors not handled */
  config->errors = NULL; /* closed elsewhere when appropriate */

  curl_slist_free_all(config->quote);
  curl_slist_free_all(config->postquote);
@@ -118,7 +128,6 @@ void free_config_fields(struct Configurable *config)

  Curl_safefree(config->libcurl);

  /* config->outs not handled */

  config->outs = NULL; /* closed elsewhere when appropriate */
}
+0 −3
Original line number Diff line number Diff line
@@ -58,9 +58,6 @@ struct OutStruct {
 * or a file descriptor as returned from an 'open' call for some file.
 *
 * 'config' member is a pointer to associated 'Configurable' struct.
 *
 * TODO: evaluate if an additional struct member should be added to
 * allow easier handling of 'stdin' vs other 'file' descriptors.
 */

struct InStruct {