diff options
author | Jeff King <peff@peff.net> | 2016-10-03 16:36:04 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-10-10 13:52:36 -0700 |
commit | 38dbe5f07837afceaec95fae5981d36eeb4917bd (patch) | |
tree | c8b54f0504b7c23df0927b393faf0fe5dc6256e1 /sha1_file.c | |
parent | afbba2f09ab06424d8b38908f4d76a1503f49a25 (diff) | |
download | git-38dbe5f07837afceaec95fae5981d36eeb4917bd.tar.gz |
alternates: store scratch buffer as strbuf
We pre-size the scratch buffer to hold a loose object
filename of the form "xx/yyyy...", which leads to allocation
code that is hard to verify. We have to use some magic
numbers during the initial allocation, and then writers must
blindly assume that the buffer is big enough. Using a strbuf
makes it more clear that we cannot overflow.
Unfortunately, we do still need some magic numbers to grow
our strbuf before calling fill_sha1_path(), but the strbuf
growth is much closer to the point of use. This makes it
easier to see that it's correct, and opens the possibility
of pushing it even further down if fill_sha1_path() learns
to work on strbufs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sha1_file.c')
-rw-r--r-- | sha1_file.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/sha1_file.c b/sha1_file.c index da7b922605..51d40241a7 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -204,11 +204,24 @@ const char *sha1_file_name(const unsigned char *sha1) return buf; } +struct strbuf *alt_scratch_buf(struct alternate_object_database *alt) +{ + strbuf_setlen(&alt->scratch, alt->base_len); + return &alt->scratch; +} + static const char *alt_sha1_path(struct alternate_object_database *alt, const unsigned char *sha1) { - fill_sha1_path(alt->name, sha1); - return alt->scratch; + /* hex sha1 plus internal "/" */ + size_t len = GIT_SHA1_HEXSZ + 1; + struct strbuf *buf = alt_scratch_buf(alt); + + strbuf_grow(buf, len); + fill_sha1_path(buf->buf + buf->len, sha1); + strbuf_setlen(buf, buf->len + len); + + return buf->buf; } /* @@ -396,16 +409,11 @@ void read_info_alternates(const char * relative_base, int depth) struct alternate_object_database *alloc_alt_odb(const char *dir) { struct alternate_object_database *ent; - size_t dirlen = strlen(dir); - size_t entlen; - entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */ FLEX_ALLOC_STR(ent, path, dir); - ent->scratch = xmalloc(entlen); - xsnprintf(ent->scratch, entlen, "%s/", dir); - - ent->name = ent->scratch + dirlen + 1; - ent->scratch[dirlen] = '/'; + strbuf_init(&ent->scratch, 0); + strbuf_addf(&ent->scratch, "%s/", dir); + ent->base_len = ent->scratch.len; return ent; } |