diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2017-12-18 23:08:40 +0000 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-02-01 16:50:30 -0800 |
commit | 1118ba3eaf5bbb28637b85ad006cce2e804a82d4 (patch) | |
tree | 92987e131c3febd433ad58e1cf8d4f273073ab11 | |
parent | 4c7a16b7aba984476150a81b38ef194289474828 (diff) | |
download | libgit2-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.c | 66 |
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; } |