summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2017-12-18 23:08:40 +0000
committerEdward Thomson <ethomson@edwardthomson.com>2018-02-01 16:50:30 -0800
commit1118ba3eaf5bbb28637b85ad006cce2e804a82d4 (patch)
tree92987e131c3febd433ad58e1cf8d4f273073ab11
parent4c7a16b7aba984476150a81b38ef194289474828 (diff)
downloadlibgit2-1118ba3eaf5bbb28637b85ad006cce2e804a82d4.tar.gz
odb_loose: `read_header` for packlike loose objects
Support `read_header` for "packlike loose objects", which were a temporarily and uncommonly used format loose object format that encodes the header before the zlib deflate data. This will never actually be seen in the wild, but add support for it for completeness and (more importantly) because our corpus of test data has objects in this format, so it's easier to support it than to try to special case it.
-rw-r--r--src/odb_loose.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/src/odb_loose.c b/src/odb_loose.c
index f01debf62..ffb2a4759 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -363,12 +363,48 @@ done:
return error;
}
-static int read_header_loose(git_rawobj *out, git_buf *loc)
+static int read_header_loose_packlike(
+ git_rawobj *out, const unsigned char *data, size_t len)
+{
+ obj_hdr hdr;
+ size_t header_len;
+ int error;
+
+ if ((error = parse_header_packlike(&hdr, &header_len, data, len)) < 0)
+ return error;
+
+ out->len = hdr.size;
+ out->type = hdr.type;
+
+ return error;
+}
+
+static int read_header_loose_standard(
+ git_rawobj *out, const unsigned char *data, size_t len)
{
git_zstream zs = GIT_ZSTREAM_INIT;
- unsigned char obj[1024], inflated[HEADER_LEN];
- size_t inflated_len, header_len;
obj_hdr hdr;
+ unsigned char inflated[HEADER_LEN];
+ size_t header_len, inflated_len = sizeof(inflated);
+ int error;
+
+ if ((error = git_zstream_init(&zs, GIT_ZSTREAM_INFLATE)) < 0 ||
+ (error = git_zstream_set_input(&zs, data, len)) < 0 ||
+ (error = git_zstream_get_output_chunk(inflated, &inflated_len, &zs)) < 0 ||
+ (error = parse_header(&hdr, &header_len, inflated, inflated_len)) < 0)
+ goto done;
+
+ out->len = hdr.size;
+ out->type = hdr.type;
+
+done:
+ git_zstream_free(&zs);
+ return error;
+}
+
+static int read_header_loose(git_rawobj *out, git_buf *loc)
+{
+ unsigned char obj[1024];
int fd, obj_len, error;
assert(out && loc);
@@ -378,33 +414,23 @@ static int read_header_loose(git_rawobj *out, git_buf *loc)
out->data = NULL;
- if ((fd = git_futils_open_ro(loc->ptr)) < 0)
- return fd;
-
- if ((error = obj_len = p_read(fd, obj, sizeof(obj))) < 0)
+ if ((error = fd = git_futils_open_ro(loc->ptr)) < 0 ||
+ (error = obj_len = p_read(fd, obj, sizeof(obj))) < 0)
goto done;
- inflated_len = sizeof(inflated);
-
- if ((error = git_zstream_init(&zs, GIT_ZSTREAM_INFLATE)) < 0 ||
- (error = git_zstream_set_input(&zs, obj, obj_len)) < 0 ||
- (error = git_zstream_get_output_chunk(inflated, &inflated_len, &zs)) < 0 ||
- (error = parse_header(&hdr, &header_len, inflated, inflated_len)) < 0)
- goto done;
+ if (!is_zlib_compressed_data(obj))
+ error = read_header_loose_packlike(out, obj, (size_t)obj_len);
+ else
+ error = read_header_loose_standard(out, obj, (size_t)obj_len);
- if (!git_object_typeisloose(hdr.type)) {
+ if (!error && !git_object_typeisloose(out->type)) {
giterr_set(GITERR_ZLIB, "failed to read loose object header");
error = -1;
goto done;
}
- out->len = hdr.size;
- out->type = hdr.type;
-
done:
- git_zstream_free(&zs);
p_close(fd);
-
return error;
}