Skip to content

Commit 38dbe5f

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent afbba2f commit 38dbe5f

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

cache.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,8 +1384,9 @@ extern void remove_scheduled_dirs(void);
13841384
extern struct alternate_object_database {
13851385
struct alternate_object_database *next;
13861386

1387-
char *name;
1388-
char *scratch;
1387+
/* see alt_scratch_buf() */
1388+
struct strbuf scratch;
1389+
size_t base_len;
13891390

13901391
char path[FLEX_ARRAY];
13911392
} *alt_odb_list;
@@ -1414,6 +1415,14 @@ extern void add_to_alternates_file(const char *dir);
14141415
*/
14151416
extern void add_to_alternates_memory(const char *dir);
14161417

1418+
/*
1419+
* Returns a scratch strbuf pre-filled with the alternate object directory,
1420+
* including a trailing slash, which can be used to access paths in the
1421+
* alternate. Always use this over direct access to alt->scratch, as it
1422+
* cleans up any previous use of the scratch buffer.
1423+
*/
1424+
extern struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
1425+
14171426
struct pack_window {
14181427
struct pack_window *next;
14191428
unsigned char *base;

sha1_file.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,24 @@ const char *sha1_file_name(const unsigned char *sha1)
204204
return buf;
205205
}
206206

207+
struct strbuf *alt_scratch_buf(struct alternate_object_database *alt)
208+
{
209+
strbuf_setlen(&alt->scratch, alt->base_len);
210+
return &alt->scratch;
211+
}
212+
207213
static const char *alt_sha1_path(struct alternate_object_database *alt,
208214
const unsigned char *sha1)
209215
{
210-
fill_sha1_path(alt->name, sha1);
211-
return alt->scratch;
216+
/* hex sha1 plus internal "/" */
217+
size_t len = GIT_SHA1_HEXSZ + 1;
218+
struct strbuf *buf = alt_scratch_buf(alt);
219+
220+
strbuf_grow(buf, len);
221+
fill_sha1_path(buf->buf + buf->len, sha1);
222+
strbuf_setlen(buf, buf->len + len);
223+
224+
return buf->buf;
212225
}
213226

214227
/*
@@ -396,16 +409,11 @@ void read_info_alternates(const char * relative_base, int depth)
396409
struct alternate_object_database *alloc_alt_odb(const char *dir)
397410
{
398411
struct alternate_object_database *ent;
399-
size_t dirlen = strlen(dir);
400-
size_t entlen;
401412

402-
entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
403413
FLEX_ALLOC_STR(ent, path, dir);
404-
ent->scratch = xmalloc(entlen);
405-
xsnprintf(ent->scratch, entlen, "%s/", dir);
406-
407-
ent->name = ent->scratch + dirlen + 1;
408-
ent->scratch[dirlen] = '/';
414+
strbuf_init(&ent->scratch, 0);
415+
strbuf_addf(&ent->scratch, "%s/", dir);
416+
ent->base_len = ent->scratch.len;
409417

410418
return ent;
411419
}

sha1_name.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,12 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
9292

9393
xsnprintf(hex, sizeof(hex), "%.2s", hex_pfx);
9494
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
95+
struct strbuf *buf = alt_scratch_buf(alt);
9596
struct dirent *de;
9697
DIR *dir;
9798

98-
/*
99-
* every alt_odb struct has 42 extra bytes after the base
100-
* for exactly this purpose
101-
*/
102-
xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
103-
dir = opendir(alt->scratch);
99+
strbuf_addf(buf, "%.2s/", hex_pfx);
100+
dir = opendir(buf->buf);
104101
if (!dir)
105102
continue;
106103

0 commit comments

Comments
 (0)