curl / Mailing Lists / curl-library / Single Mail

curl-library

RE: Access violation in Curl_hash_add

From: Jake Fehr (jfehr) <jfehr_at_cisco.com>
Date: Fri, 9 Dec 2016 16:29:55 +0000

Thank you Ray and Daniel for the quick response. Our application is multithreaded and different threads will use it (Curl) for their own purposes but the code here is isolated to a single thread (there is no sharing of curl objects).

This is the code that is using curl:

               CURL *curl_handle;
               CURLcode curlcode;
               const char *server_addr_str;
               const char *proxy;
               int proxyauth = CURLAUTH_NONE;
               time_t send_ts = 0;
               long cache_timeout_age = CURL_DEFAULT_DNS_CACHE_TIMEOUT;
               long fresh_connect = CURL_DEFAULT_FRESH_CONNECT;
               int iResult;

               curl_handle = curl_easy_init();
               if (!(curl_handle)) {
                              printf("%s(): curl_easy_init returned NULL", __func__);
                              goto ERROUT;
               }
               // with libcurl, necessary to use http:// or https:// even though the protocol is not http
               snprintf(url, sizeof(url), "https://%s:%d", handle->server_name, port);
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_URL, url);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_URL) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               if (proxy) {
                              curlcode = curl_easy_setopt(curl_handle, CURLOPT_PROXY, proxy);
                              if (curlcode != CURLE_OK) {
                                             printf("%s(): curl_easy_setopt(CURLOPT_PROXY) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                                             curl_easy_cleanup(curl_handle);
                                             goto ERROUT;
                              }
                              // if using an HTTP proxy, do a CONNECT
                              curlcode = curl_easy_setopt(curl_handle, CURLOPT_HTTPPROXYTUNNEL, 1);
                              if (curlcode != CURLE_OK) {
                                             printf("%s(): curl_easy_setopt(CURLOPT_HTTPPROXYTUNNEL) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                                             curl_easy_cleanup(curl_handle);
                                             goto ERROUT;
                              }
                              if (proxyauth != CURLAUTH_NONE) {
                                             curlcode = curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, proxyauth);
                                             if (curlcode != CURLE_OK) {
                                                            printf("%s(): curl_easy_setopt(CURLOPT_PROXYAUTH) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                                                            curl_easy_cleanup(curl_handle);
                                                            goto ERROUT;
                                             }
                              }
                              send_ts = time(NULL);
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_PORT, port);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_PORT) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_CONNECT_ONLY, 1);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_CONNECT_ONLY) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); // XXX TODO a few changes needed for ipv6
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_IPRESOLVE) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_CTX_FUNCTION, *fa_sslctx_config_func);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_SSL_CTX_FUNCTION) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_CTX_DATA, handle);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_SSL_CTX_DATA) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }

               curlcode = curl_easy_setopt(curl_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_USE_SSL) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, insecure ? 0 : 1);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_SSL_VERIFYPEER) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, insecure ? 0 : 2);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_SSL_VERIFYHOST) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_NOSIGNAL) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, handle->curl_error);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_ERRORBUFFER) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              curl_easy_cleanup(curl_handle);
                              goto ERROUT;
               }

               if (fresh_connection) {
                              fresh_connect = 1L;
                              cache_timeout_age = 0L;
                              handle->last_connection_refresh = time(NULL);
                              handle->force_fresh_connection = false;
                              printf("%s(): Forcing connection refresh and clearing DNS cache", __func__);
               }

               curlcode = curl_easy_setopt(curl_handle, CURLOPT_FRESH_CONNECT, fresh_connect);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_FRESH_CONNECT) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              /* the rest of the connection has been setup properly, continue on error */
               }
               curlcode = curl_easy_setopt(curl_handle, CURLOPT_DNS_CACHE_TIMEOUT, cache_timeout_age);
               if (curlcode != CURLE_OK) {
                              printf("%s(): curl_easy_setopt(CURLOPT_DNS_CACHE_TIMEOUT) returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
                              /* the rest of the connection has been setup properly, continue on error */
               }

               printf("%s(): running curl_easy_perform", __func__);
               curlcode = curl_easy_perform(curl_handle);
               if (curlcode != CURLE_OK) {
                              switch (curlcode) {
                                             case CURLE_SSL_CERTPROBLEM:
                                                            printf("%s(): received curl error: %s for %s port %d, we will assume that our certificate is bad, we remove current "
                                                                                            "certificate to obtain a new one via EST", __func__, curl_easy_strerror(curlcode), url, port);
                                                            break;

                                             case CURLE_SSL_CACERT:
                                                            printf("%s(): received curl error: %s for %s port %d we need to manually obtain a new CA certificate", __func__,
                                                                                            curl_easy_strerror(curlcode), url, port);
                                                            break;

                                             case CURLE_SSL_CONNECT_ERROR:
                                                            if (strncmp(handle->curl_error, CURL_UNKNOWN_CA_SSL_ERROR, sizeof(CURL_UNKNOWN_CA_SSL_ERROR) - 1) == 0) {
                                                                           printf("%s(): curl_easy_perform returned SSL connect error for %s port %d.",
                                                                                                           __func__, url, port);
                                                            } else {
                                                                           printf("%s(): curl_easy_perform SSL connect error (%s) for %s port %d", __func__, handle->curl_error, url, port);
                                                            }
                                                            break;

                                             case CURLE_COULDNT_RESOLVE_PROXY:
                                             case CURLE_COULDNT_RESOLVE_HOST:
                                                            /* When running from a VM, on wake we sometimes see issues with resolving hostnames, force a fresh connection on next request */
                                                            if ((handle->last_connection_refresh == 0) ||
                                                                           ((time(NULL) - handle->last_connection_refresh) > MIN_CONNECTION_REFRESH_PERIOD)) {
                                                                           handle->force_fresh_connection = true;
                                                            }
                                                            /* fall through */
                                             default:
                                                            printf("%s(): curl_easy_perform for %s port %d returned %d (%s) (%s)", __func__, url, port, curlcode,
                                                                                            curl_easy_strerror(curlcode), handle->curl_error);
                                                            break;
                              }
                              curl_easy_cleanup(curl_handle);
                              /*
                               * Here we differentiate between whether a server is unreachable
                              * or another error has occurred such as a timeouts or an invalid
                              * response from the server.
                              *
                              * We consider the server unreachable if we can't connect to it,
                              * we failed to resolve the host/proxy, we've been
                              * redirected too many times or an SSL connect error was
                              * encountered.
                              */
                              if ((curlcode == CURLE_COULDNT_CONNECT) ||
                                             (curlcode == CURLE_COULDNT_RESOLVE_HOST) ||
                                             (curlcode == CURLE_COULDNT_RESOLVE_PROXY) ||
                                             (curlcode == CURLE_TOO_MANY_REDIRECTS) ||
                                             (curlcode == CURLE_SSL_CONNECT_ERROR)) {
                                             if (handle->connection_failed_cb) {
                                                            handle->connection_failed_cb(send_ts);
                                             }
                              } else if (handle->connection_reachable_cb) {
                                             handle->connection_reachable_cb();
                              }
                              goto ERROUT;
               }
               printf("%s(): curl_easy_perform returned", __func__);


From: curl-library [mailto:curl-library-bounces_at_cool.haxx.se] On Behalf Of Ray Satiro via curl-library
Sent: Thursday, December 08, 2016 4:44 PM
To: curl-library_at_cool.haxx.se
Cc: Ray Satiro <raysatiro_at_yahoo.com>
Subject: Re: Access violation in Curl_hash_add

On 12/8/2016 6:27 PM, Jake Fehr (jfehr) wrote:

Our use of Curl is pretty straightforward:


1. Call curl_easy_init()

2. Make (and check the result of) several calls to curl_easy_setopt(), setting up proxy, url, port, ssl, etc.

3. Call curl_easy_perform()

I can provide the code if needed.

Please provide a self contained example that can be used to reproduce, your curl_version() and the OS you're using.

-------------------------------------------------------------------
List admin: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2016-12-09