Merge branch 'dt/http-postbuffer-can-be-large'
authorJunio C Hamano <gitster@pobox.com>
Mon, 24 Apr 2017 05:07:45 +0000 (22:07 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 24 Apr 2017 05:07:45 +0000 (22:07 -0700)
Allow the http.postbuffer configuration variable to be set to a
size that can be expressed in size_t, which can be larger than
ulong on some platforms.

* dt/http-postbuffer-can-be-large:
http.postbuffer: allow full range of ssize_t values

1  2 
cache.h
http.c
remote-curl.c
diff --combined cache.h
index ba27595d54d864f600cb537e531e8855b8b0bdb6,3c76ba662945ad6f48dd1c87c46dc6badba74c61..e5cc06987a5bf20b72168591e9897699883b41cf
+++ b/cache.h
@@@ -66,12 -66,8 +66,12 @@@ unsigned long git_deflate_bound(git_zst
  #define GIT_SHA1_RAWSZ 20
  #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
  
 +/* The length in byte and in hex digits of the largest possible hash value. */
 +#define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
 +#define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
 +
  struct object_id {
 -      unsigned char hash[GIT_SHA1_RAWSZ];
 +      unsigned char hash[GIT_MAX_RAWSZ];
  };
  
  #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
@@@ -982,7 -978,7 +982,7 @@@ extern char *sha1_pack_index_name(cons
  extern const char *find_unique_abbrev(const unsigned char *sha1, int len);
  extern int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len);
  
 -extern const unsigned char null_sha1[GIT_SHA1_RAWSZ];
 +extern const unsigned char null_sha1[GIT_MAX_RAWSZ];
  extern const struct object_id null_oid;
  
  static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
@@@ -1364,7 -1360,7 +1364,7 @@@ extern int get_sha1_with_context(const 
  
  extern int get_oid(const char *str, struct object_id *oid);
  
 -typedef int each_abbrev_fn(const unsigned char *sha1, void *);
 +typedef int each_abbrev_fn(const struct object_id *oid, void *);
  extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
  
  extern int set_disambiguate_hint_config(const char *var, const char *value);
@@@ -1679,12 -1675,9 +1679,12 @@@ extern struct packed_git *find_sha1_pac
  extern void pack_report(void);
  
  /*
 - * Create a temporary file rooted in the object database directory.
 + * Create a temporary file rooted in the object database directory, or
 + * die on failure. The filename is taken from "pattern", which should have the
 + * usual "XXXXXX" trailer, and the resulting filename is written into the
 + * "template" buffer. Returns the open descriptor.
   */
 -extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 +extern int odb_mkstemp(struct strbuf *template, const char *pattern);
  
  /*
   * Generate the filename to be used for a pack file with checksum "sha1" and
@@@ -1908,6 -1901,7 +1908,7 @@@ extern int git_parse_maybe_bool(const c
  extern int git_config_int(const char *, const char *);
  extern int64_t git_config_int64(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
+ extern ssize_t git_config_ssize_t(const char *, const char *);
  extern int git_config_bool_or_int(const char *, const char *, int *);
  extern int git_config_bool(const char *, const char *);
  extern int git_config_maybe_bool(const char *, const char *);
diff --combined http.c
index 7a168ed5a8cfef2cae6a4da044344940adbb82e1,7bccb3645958a07df578c943a97c0dc6f266de6e..d2e11ec6f012d3b2a9570f0c322aebf53a13cc0a
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -19,7 -19,7 +19,7 @@@ long int git_curl_ipresolve
  #endif
  int active_requests;
  int http_is_verbose;
- size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
+ ssize_t http_post_buffer = 16 * LARGE_PACKET_MAX;
  
  #if LIBCURL_VERSION_NUM >= 0x070a06
  #define LIBCURL_CAN_HANDLE_AUTH_ANY
@@@ -331,7 -331,9 +331,9 @@@ static int http_options(const char *var
        }
  
        if (!strcmp("http.postbuffer", var)) {
-               http_post_buffer = git_config_int(var, value);
+               http_post_buffer = git_config_ssize_t(var, value);
+               if (http_post_buffer < 0)
+                       warning(_("negative value for http.postbuffer; defaulting to %d"), LARGE_PACKET_MAX);
                if (http_post_buffer < LARGE_PACKET_MAX)
                        http_post_buffer = LARGE_PACKET_MAX;
                return 0;
@@@ -836,14 -838,8 +838,14 @@@ static CURL *get_curl_handle(void
                }
        }
  
 -      if (curl_http_proxy) {
 -              curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
 +      if (curl_http_proxy && curl_http_proxy[0] == '\0') {
 +              /*
 +               * Handle case with the empty http.proxy value here to keep
 +               * common code clean.
 +               * NB: empty option disables proxying at all.
 +               */
 +              curl_easy_setopt(result, CURLOPT_PROXY, "");
 +      } else if (curl_http_proxy) {
  #if LIBCURL_VERSION_NUM >= 0x071800
                if (starts_with(curl_http_proxy, "socks5h"))
                        curl_easy_setopt(result,
                        strbuf_release(&url);
                }
  
 +              if (!proxy_auth.host)
 +                      die("Invalid proxy URL '%s'", curl_http_proxy);
 +
                curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
  #if LIBCURL_VERSION_NUM >= 0x071304
                var_override(&curl_no_proxy, getenv("NO_PROXY"));
@@@ -1375,9 -1368,9 +1377,9 @@@ static int handle_curl_result(struct sl
                 * FAILONERROR it is lost, so we can give only the numeric
                 * status code.
                 */
 -              snprintf(curl_errorstr, sizeof(curl_errorstr),
 -                       "The requested URL returned error: %ld",
 -                       results->http_code);
 +              xsnprintf(curl_errorstr, sizeof(curl_errorstr),
 +                        "The requested URL returned error: %ld",
 +                        results->http_code);
        }
  
        if (results->curl_result == CURLE_OK) {
@@@ -1419,8 -1412,8 +1421,8 @@@ int run_one_slot(struct active_request_
  {
        slot->results = results;
        if (!start_active_slot(slot)) {
 -              snprintf(curl_errorstr, sizeof(curl_errorstr),
 -                       "failed to start HTTP request");
 +              xsnprintf(curl_errorstr, sizeof(curl_errorstr),
 +                        "failed to start HTTP request");
                return HTTP_START_FAILED;
        }
  
diff --combined remote-curl.c
index d41fe16ff320e889820a6cb04ad941770415c6d2,cf171b1bc95cd66f63c14e3337c3c91646262212..ece45993dac582ddc6ba19b2362ba1716e075eae
@@@ -167,7 -167,7 +167,7 @@@ struct discovery 
        char *buf;
        size_t len;
        struct ref *refs;
 -      struct sha1_array shallow;
 +      struct oid_array shallow;
        unsigned proto_git : 1;
  };
  static struct discovery *last_discovery;
@@@ -234,7 -234,7 +234,7 @@@ static void free_discovery(struct disco
        if (d) {
                if (d == last_discovery)
                        last_discovery = NULL;
 -              free(d->shallow.sha1);
 +              free(d->shallow.oid);
                free(d->buf_alloc);
                free_refs(d->refs);
                free(d);
@@@ -531,6 -531,12 +531,12 @@@ static int probe_rpc(struct rpc_state *
        return err;
  }
  
+ static curl_off_t xcurl_off_t(ssize_t len) {
+       if (len > maximum_signed_value_of_type(curl_off_t))
+               die("cannot handle pushes this big");
+       return (curl_off_t) len;
+ }
  static int post_rpc(struct rpc_state *rpc)
  {
        struct active_request_slot *slot;
@@@ -614,7 -620,7 +620,7 @@@ retry
                 * and we just need to send it.
                 */
                curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
-               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
+               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE_LARGE, xcurl_off_t(gzip_size));
  
        } else if (use_gzip && 1024 < rpc->len) {
                /* The client backend isn't giving us compressed data so
  
                headers = curl_slist_append(headers, "Content-Encoding: gzip");
                curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
-               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
+               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE_LARGE, xcurl_off_t(gzip_size));
  
                if (options.verbosity > 1) {
                        fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n",
                 * more normal Content-Length approach.
                 */
                curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, rpc->buf);
-               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, rpc->len);
+               curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE_LARGE, xcurl_off_t(rpc->len));
                if (options.verbosity > 1) {
                        fprintf(stderr, "POST %s (%lu bytes)\n",
                                rpc->service_name, (unsigned long)rpc->len);