Fix git-am safety checks
[gitweb.git] / http-fetch.c
index 7f07d2a967fdecb497344817700962e9e213d3dd..a113bb8c4b0c8d59b5b6df3c7689ba9f50818753 100644 (file)
@@ -301,7 +301,7 @@ static void finish_object_request(struct object_request *obj_req)
                unlink(obj_req->tmpfile);
                return;
        }
-       if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
+       if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
                unlink(obj_req->tmpfile);
                return;
        }
@@ -393,7 +393,7 @@ void prefetch(unsigned char *sha1)
        char *filename = sha1_file_name(sha1);
 
        newreq = xmalloc(sizeof(*newreq));
-       memcpy(newreq->sha1, sha1, 20);
+       hashcpy(newreq->sha1, sha1);
        newreq->repo = alt;
        newreq->url = NULL;
        newreq->local = -1;
@@ -559,9 +559,36 @@ static void process_alternates_response(void *callback_data)
                        char *target = NULL;
                        char *path;
                        if (data[i] == '/') {
-                               serverlen = strchr(base + 8, '/') - base;
-                               okay = 1;
+                               /* This counts
+                                * http://git.host/pub/scm/linux.git/
+                                * -----------here^
+                                * so memcpy(dst, base, serverlen) will
+                                * copy up to "...git.host".
+                                */
+                               const char *colon_ss = strstr(base,"://");
+                               if (colon_ss) {
+                                       serverlen = (strchr(colon_ss + 3, '/')
+                                                    - base);
+                                       okay = 1;
+                               }
                        } else if (!memcmp(data + i, "../", 3)) {
+                               /* Relative URL; chop the corresponding
+                                * number of subpath from base (and ../
+                                * from data), and concatenate the result.
+                                *
+                                * The code first drops ../ from data, and
+                                * then drops one ../ from data and one path
+                                * from base.  IOW, one extra ../ is dropped
+                                * from data than path is dropped from base.
+                                *
+                                * This is not wrong.  The alternate in
+                                *     http://git.host/pub/scm/linux.git/
+                                * to borrow from
+                                *     http://git.host/pub/scm/linus.git/
+                                * is ../../linus.git/objects/.  You need
+                                * two ../../ to borrow from your direct
+                                * neighbour.
+                                */
                                i += 3;
                                serverlen = strlen(base);
                                while (i + 2 < posn &&
@@ -583,11 +610,13 @@ static void process_alternates_response(void *callback_data)
                                        okay = 1;
                                }
                        }
-                       /* skip 'objects' at end */
+                       /* skip "objects\n" at end */
                        if (okay) {
                                target = xmalloc(serverlen + posn - i - 6);
-                               strlcpy(target, base, serverlen);
-                               strlcpy(target + serverlen, data + i, posn - i - 6);
+                               memcpy(target, base, serverlen);
+                               memcpy(target + serverlen, data + i,
+                                      posn - i - 7);
+                               target[serverlen + posn - i - 7] = 0;
                                if (get_verbosely)
                                        fprintf(stderr,
                                                "Also look at %s\n", target);
@@ -696,10 +725,8 @@ xml_start_tag(void *userData, const char *name, const char **atts)
        strcat(ctx->name, ".");
        strcat(ctx->name, c);
 
-       if (ctx->cdata) {
-               free(ctx->cdata);
-               ctx->cdata = NULL;
-       }
+       free(ctx->cdata);
+       ctx->cdata = NULL;
 
        ctx->userFunc(ctx, 0);
 }
@@ -726,8 +753,7 @@ static void
 xml_cdata(void *userData, const XML_Char *s, int len)
 {
        struct xml_ctx *ctx = (struct xml_ctx *)userData;
-       if (ctx->cdata)
-               free(ctx->cdata);
+       free(ctx->cdata);
        ctx->cdata = xmalloc(len + 1);
        strlcpy(ctx->cdata, s, len + 1);
 }
@@ -765,9 +791,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
                        ls->dentry_flags |= IS_DIR;
                }
        } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
-               if (ls->dentry_name) {
-                       free(ls->dentry_name);
-               }
+               free(ls->dentry_name);
                ls->dentry_name = NULL;
                ls->dentry_flags = 0;
        }
@@ -792,7 +816,7 @@ static int remote_ls(struct alt_base *repo, const char *path, int flags,
 
        ls.flags = flags;
        ls.repo = repo;
-       ls.path = strdup(path);
+       ls.path = xstrdup(path);
        ls.dentry_name = NULL;
        ls.dentry_flags = 0;
        ls.userData = userData;
@@ -1070,7 +1094,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
        int ret = 0;
        struct object_request *obj_req = object_queue_head;
 
-       while (obj_req != NULL && memcmp(obj_req->sha1, sha1, 20))
+       while (obj_req != NULL && hashcmp(obj_req->sha1, sha1))
                obj_req = obj_req->next;
        if (obj_req == NULL)
                return error("Couldn't find request for %s in the queue", hex);
@@ -1109,7 +1133,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
        } else if (obj_req->zret != Z_STREAM_END) {
                corrupt_object_found++;
                ret = error("File %s (%s) corrupt", hex, obj_req->url);
-       } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) {
+       } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
                ret = error("File %s has bad hash", hex);
        } else if (obj_req->rename < 0) {
                ret = error("unable to write sha1 filename %s",