]> git.ipfire.org Git - thirdparty/git.git/commitdiff
http: simplify parsing of remote objects/info/packs
authorJeff King <peff@peff.net>
Fri, 5 Apr 2019 18:12:55 +0000 (14:12 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 07:58:21 +0000 (16:58 +0900)
We can use skip_prefix() and parse_oid_hex() to continuously increment
our pointer, rather than dealing with magic numbers. This also fixes a
few small shortcomings:

  - if we see a line with the right prefix, suffix, and length, i.e.
    matching /P pack-.{40}.pack\n/, we'll interpret the middle part as
    hex without checking if it could be parsed. This could lead to us
    looking at uninitialized garbage in the hash array. In practice this
    means we'll just make a garbage request to the server which will
    fail, though it's interesting that a malicious server could convince
    us to leak 40 bytes of uninitialized stack to them.

  - the current code is picky about seeing a newline at the end of file,
    but we can easily be more liberal

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
http.c

diff --git a/http.c b/http.c
index a32ad36ddf6b813ce0e02c85e7b61b4613517a9c..2ef47bc7798d87e9c4f2c6ff66c99e3db073048f 100644 (file)
--- a/http.c
+++ b/http.c
@@ -2147,11 +2147,11 @@ add_pack:
 int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
 {
        struct http_get_options options = {0};
-       int ret = 0, i = 0;
-       char *url, *data;
+       int ret = 0;
+       char *url;
+       const char *data;
        struct strbuf buf = STRBUF_INIT;
-       unsigned char hash[GIT_MAX_RAWSZ];
-       const unsigned hexsz = the_hash_algo->hexsz;
+       struct object_id oid;
 
        end_url_with_slash(&buf, base_url);
        strbuf_addstr(&buf, "objects/info/packs");
@@ -2163,24 +2163,17 @@ int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
                goto cleanup;
 
        data = buf.buf;
-       while (i < buf.len) {
-               switch (data[i]) {
-               case 'P':
-                       i++;
-                       if (i + hexsz + 12 <= buf.len &&
-                           starts_with(data + i, " pack-") &&
-                           starts_with(data + i + hexsz + 6, ".pack\n")) {
-                               get_sha1_hex(data + i + 6, hash);
-                               fetch_and_setup_pack_index(packs_head, hash,
-                                                     base_url);
-                               i += hexsz + 11;
-                               break;
-                       }
-               default:
-                       while (i < buf.len && data[i] != '\n')
-                               i++;
+       while (*data) {
+               if (skip_prefix(data, "P pack-", &data) &&
+                   !parse_oid_hex(data, &oid, &data) &&
+                   skip_prefix(data, ".pack", &data) &&
+                   (*data == '\n' || *data == '\0')) {
+                       fetch_and_setup_pack_index(packs_head, oid.hash, base_url);
+               } else {
+                       data = strchrnul(data, '\n');
                }
-               i++;
+               if (*data)
+                       data++; /* skip past newline */
        }
 
 cleanup: