Merge branch 'maint-1.6.1' into maint-1.6.2
authorJunio C Hamano <gitster@pobox.com>
Sun, 24 May 2009 22:29:23 +0000 (15:29 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 24 May 2009 22:29:23 +0000 (15:29 -0700)
* maint-1.6.1:
  http-push.c::remove_locks(): fix use after free

1  2 
http-push.c

diff --combined http-push.c
index 968b6b0662a89d437e53bcc699c65e98a745f659,f743c9796a369a44c84238c244314da3c7b45dab..f101df40861a13db40cb2f564476369f3765a28f
@@@ -10,7 -10,6 +10,7 @@@
  #include "exec_cmd.h"
  #include "remote.h"
  #include "list-objects.h"
 +#include "sigchain.h"
  
  #include <expat.h>
  
@@@ -153,7 -152,6 +153,7 @@@ struct remote_loc
        char *url;
        char *owner;
        char *token;
 +      char tmpfile_suffix[41];
        time_t start_time;
        long timeout;
        int refreshing;
@@@ -179,47 -177,6 +179,47 @@@ struct remote_ls_ct
        struct remote_ls_ctx *parent;
  };
  
 +/* get_dav_token_headers options */
 +enum dav_header_flag {
 +      DAV_HEADER_IF = (1u << 0),
 +      DAV_HEADER_LOCK = (1u << 1),
 +      DAV_HEADER_TIMEOUT = (1u << 2)
 +};
 +
 +static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      struct curl_slist *dav_headers = NULL;
 +
 +      if (options & DAV_HEADER_IF) {
 +              strbuf_addf(&buf, "If: (<%s>)", lock->token);
 +              dav_headers = curl_slist_append(dav_headers, buf.buf);
 +              strbuf_reset(&buf);
 +      }
 +      if (options & DAV_HEADER_LOCK) {
 +              strbuf_addf(&buf, "Lock-Token: <%s>", lock->token);
 +              dav_headers = curl_slist_append(dav_headers, buf.buf);
 +              strbuf_reset(&buf);
 +      }
 +      if (options & DAV_HEADER_TIMEOUT) {
 +              strbuf_addf(&buf, "Timeout: Second-%ld", lock->timeout);
 +              dav_headers = curl_slist_append(dav_headers, buf.buf);
 +              strbuf_reset(&buf);
 +      }
 +      strbuf_release(&buf);
 +
 +      return dav_headers;
 +}
 +
 +static void append_remote_object_url(struct strbuf *buf, const char *url,
 +                                   const char *hex,
 +                                   int only_two_digit_prefix)
 +{
 +      strbuf_addf(buf, "%sobjects/%.*s/", url, 2, hex);
 +      if (!only_two_digit_prefix)
 +              strbuf_addf(buf, "%s", hex+2);
 +}
 +
  static void finish_request(struct transfer_request *request);
  static void release_request(struct transfer_request *request);
  
@@@ -232,15 -189,6 +232,15 @@@ static void process_response(void *call
  }
  
  #ifdef USE_CURL_MULTI
 +
 +static char *get_remote_object_url(const char *url, const char *hex,
 +                                 int only_two_digit_prefix)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      append_remote_object_url(&buf, url, hex, only_two_digit_prefix);
 +      return strbuf_detach(&buf, NULL);
 +}
 +
  static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
                               void *data)
  {
@@@ -275,6 -223,7 +275,6 @@@ static void start_fetch_loose(struct tr
        char *filename;
        char prevfile[PATH_MAX];
        char *url;
 -      char *posn;
        int prevlocal;
        unsigned char prev_buf[PREV_BUF_SIZE];
        ssize_t prev_read = 0;
  
        git_SHA1_Init(&request->c);
  
 -      url = xmalloc(strlen(remote->url) + 50);
 -      request->url = xmalloc(strlen(remote->url) + 50);
 -      strcpy(url, remote->url);
 -      posn = url + strlen(remote->url);
 -      strcpy(posn, "objects/");
 -      posn += 8;
 -      memcpy(posn, hex, 2);
 -      posn += 2;
 -      *(posn++) = '/';
 -      strcpy(posn, hex + 2);
 -      strcpy(request->url, url);
 +      url = get_remote_object_url(remote->url, hex, 0);
 +      request->url = xstrdup(url);
  
        /* If a previous temp file is present, process what was already
           fetched. */
@@@ -398,8 -356,16 +398,8 @@@ static void start_mkcol(struct transfer
  {
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
 -      char *posn;
  
 -      request->url = xmalloc(strlen(remote->url) + 13);
 -      strcpy(request->url, remote->url);
 -      posn = request->url + strlen(remote->url);
 -      strcpy(posn, "objects/");
 -      posn += 8;
 -      memcpy(posn, hex, 2);
 -      posn += 2;
 -      strcpy(posn, "/");
 +      request->url = get_remote_object_url(remote->url, hex, 1);
  
        slot = get_active_slot();
        slot->callback_func = process_response;
@@@ -514,7 -480,7 +514,7 @@@ static void start_put(struct transfer_r
  {
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
 -      char *posn;
 +      struct strbuf buf = STRBUF_INIT;
        enum object_type type;
        char hdr[50];
        void *unpacked;
  
        request->buffer.buf.len = stream.total_out;
  
 -      request->url = xmalloc(strlen(remote->url) +
 -                             strlen(request->lock->token) + 51);
 -      strcpy(request->url, remote->url);
 -      posn = request->url + strlen(remote->url);
 -      strcpy(posn, "objects/");
 -      posn += 8;
 -      memcpy(posn, hex, 2);
 -      posn += 2;
 -      *(posn++) = '/';
 -      strcpy(posn, hex + 2);
 -      request->dest = xmalloc(strlen(request->url) + 14);
 -      sprintf(request->dest, "Destination: %s", request->url);
 -      posn += 38;
 -      *(posn++) = '_';
 -      strcpy(posn, request->lock->token);
 +      strbuf_addstr(&buf, "Destination: ");
 +      append_remote_object_url(&buf, remote->url, hex, 0);
 +      request->dest = strbuf_detach(&buf, NULL);
 +
 +      append_remote_object_url(&buf, remote->url, hex, 0);
 +      strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
 +      request->url = strbuf_detach(&buf, NULL);
  
        slot = get_active_slot();
        slot->callback_func = process_response;
@@@ -614,12 -588,18 +614,12 @@@ static int refresh_lock(struct remote_l
  {
        struct active_request_slot *slot;
        struct slot_results results;
 -      char *if_header;
 -      char timeout_header[25];
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers;
        int rc = 0;
  
        lock->refreshing = 1;
  
 -      if_header = xmalloc(strlen(lock->token) + 25);
 -      sprintf(if_header, "If: (<%s>)", lock->token);
 -      sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
 -      dav_headers = curl_slist_append(dav_headers, if_header);
 -      dav_headers = curl_slist_append(dav_headers, timeout_header);
 +      dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF | DAV_HEADER_TIMEOUT);
  
        slot = get_active_slot();
        slot->results = &results;
  
        lock->refreshing = 0;
        curl_slist_free_all(dav_headers);
 -      free(if_header);
  
        return rc;
  }
@@@ -748,6 -729,7 +748,6 @@@ static void finish_request(struct trans
                        aborted = 1;
                }
        } else if (request->state == RUN_FETCH_LOOSE) {
 -              fchmod(request->local_fileno, 0444);
                close(request->local_fileno); request->local_fileno = -1;
  
                if (request->curl_result != CURLE_OK &&
@@@ -1129,8 -1111,6 +1129,8 @@@ static void handle_lockprop_ctx(struct 
  static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
  {
        struct remote_lock *lock = (struct remote_lock *)ctx->userData;
 +      git_SHA_CTX sha_ctx;
 +      unsigned char lock_token_sha1[20];
  
        if (tag_closed && ctx->cdata) {
                if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
                } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
                        lock->token = xmalloc(strlen(ctx->cdata) + 1);
                        strcpy(lock->token, ctx->cdata);
 +
 +                      git_SHA1_Init(&sha_ctx);
 +                      git_SHA1_Update(&sha_ctx, lock->token, strlen(lock->token));
 +                      git_SHA1_Final(lock_token_sha1, &sha_ctx);
 +
 +                      lock->tmpfile_suffix[0] = '_';
 +                      memcpy(lock->tmpfile_suffix + 1, sha1_to_hex(lock_token_sha1), 40);
                }
        }
  }
@@@ -1330,10 -1303,14 +1330,10 @@@ static int unlock_remote(struct remote_
        struct active_request_slot *slot;
        struct slot_results results;
        struct remote_lock *prev = remote->locks;
 -      char *lock_token_header;
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers;
        int rc = 0;
  
 -      lock_token_header = xmalloc(strlen(lock->token) + 31);
 -      sprintf(lock_token_header, "Lock-Token: <%s>",
 -              lock->token);
 -      dav_headers = curl_slist_append(dav_headers, lock_token_header);
 +      dav_headers = get_dav_token_headers(lock, DAV_HEADER_LOCK);
  
        slot = get_active_slot();
        slot->results = &results;
        }
  
        curl_slist_free_all(dav_headers);
 -      free(lock_token_header);
  
        if (remote->locks == lock) {
                remote->locks = lock->next;
@@@ -1378,15 -1356,16 +1378,16 @@@ static void remove_locks(void
  
        fprintf(stderr, "Removing remote locks...\n");
        while (lock) {
+               struct remote_lock *next = lock->next;
                unlock_remote(lock);
-               lock = lock->next;
+               lock = next;
        }
  }
  
  static void remove_locks_on_signal(int signo)
  {
        remove_locks();
 -      signal(signo, SIG_DFL);
 +      sigchain_pop(signo);
        raise(signo);
  }
  
@@@ -1753,10 -1732,13 +1754,10 @@@ static int update_remote(unsigned char 
  {
        struct active_request_slot *slot;
        struct slot_results results;
 -      char *if_header;
        struct buffer out_buffer = { STRBUF_INIT, 0 };
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers;
  
 -      if_header = xmalloc(strlen(lock->token) + 25);
 -      sprintf(if_header, "If: (<%s>)", lock->token);
 -      dav_headers = curl_slist_append(dav_headers, if_header);
 +      dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
  
        strbuf_addf(&out_buffer.buf, "%s\n", sha1_to_hex(sha1));
  
        if (start_active_slot(slot)) {
                run_active_slot(slot);
                strbuf_release(&out_buffer.buf);
 -              free(if_header);
                if (results.curl_result != CURLE_OK) {
                        fprintf(stderr,
                                "PUT error: curl result=%d, HTTP code=%ld\n",
                }
        } else {
                strbuf_release(&out_buffer.buf);
 -              free(if_header);
                fprintf(stderr, "Unable to start PUT request\n");
                return 0;
        }
@@@ -1965,12 -1949,15 +1966,12 @@@ static void update_remote_info_refs(str
        struct buffer buffer = { STRBUF_INIT, 0 };
        struct active_request_slot *slot;
        struct slot_results results;
 -      char *if_header;
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers;
  
        remote_ls("refs/", (PROCESS_FILES | RECURSIVE),
                  add_remote_info_ref, &buffer.buf);
        if (!aborted) {
 -              if_header = xmalloc(strlen(lock->token) + 25);
 -              sprintf(if_header, "If: (<%s>)", lock->token);
 -              dav_headers = curl_slist_append(dav_headers, if_header);
 +              dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
  
                slot = get_active_slot();
                slot->results = &results;
                                        results.curl_result, results.http_code);
                        }
                }
 -              free(if_header);
        }
        strbuf_release(&buffer.buf);
  }
@@@ -2197,8 -2185,6 +2198,8 @@@ int main(int argc, char **argv
        struct ref *ref;
        char *rewritten_url = NULL;
  
 +      git_extract_argv0_path(argv[0]);
 +
        setup_git_directory();
  
        remote = xcalloc(sizeof(*remote), 1);
                goto cleanup;
        }
  
 -      signal(SIGINT, remove_locks_on_signal);
 -      signal(SIGHUP, remove_locks_on_signal);
 -      signal(SIGQUIT, remove_locks_on_signal);
 -      signal(SIGTERM, remove_locks_on_signal);
 +      sigchain_push_common(remove_locks_on_signal);
  
        /* Check whether the remote has server info files */
        remote->can_update_info_refs = 0;