Skip to content

Commit ad2dd5b

Browse files
ttaylorrgitster
authored andcommitted
commit-graph.c: remove path normalization, comparison
As of the previous patch, all calls to 'commit-graph.c' functions which perform path normalization (for e.g., 'get_commit_graph_filename()') are of the form 'ctx->odb->path', which is always in normalized form. Now that there are no callers passing non-normalized paths to these functions, ensure that future callers are bound by the same restrictions by making these functions take a 'struct object_directory *' instead of a 'const char *'. To match, replace all calls with arguments of the form 'ctx->odb->path' with 'ctx->odb' To recover the path, functions that perform path manipulation simply use 'odb->path'. Further, avoid string comparisons with arguments of the form 'odb->path', and instead prefer raw pointer comparisons, which accomplish the same effect, but are far less brittle. This has a pleasant side-effect of making these functions much more robust to paths that cannot be normalized by 'normalize_path_copy()', i.e., because they are outside of the current working directory. For example, prior to this patch, Valgrind reports that the following uninitialized memory read [1]: $ ( cd t && GIT_DIR=../.git valgrind git rev-parse HEAD^ ) because 'normalize_path_copy()' can't normalize '../.git' (since it's relative to but above of the current working directory) [2]. By using a 'struct object_directory *' directly, 'get_commit_graph_filename()' does not need to normalize, because all paths are relative to the current working directory since they are always read from the '->path' of an object directory. [1]: https://lore.kernel.org/git/[email protected]. [2]: The bug here is that 'get_commit_graph_filename()' returns the result of 'normalize_path_copy()' without checking the return value. Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 13c2499 commit ad2dd5b

File tree

4 files changed

+24
-33
lines changed

4 files changed

+24
-33
lines changed

builtin/commit-graph.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static int graph_verify(int argc, const char **argv)
8888
flags |= COMMIT_GRAPH_WRITE_PROGRESS;
8989

9090
odb = find_odb(the_repository, opts.obj_dir);
91-
graph_name = get_commit_graph_filename(odb->path);
91+
graph_name = get_commit_graph_filename(odb);
9292
open_ok = open_commit_graph(graph_name, &fd, &st);
9393
if (!open_ok && errno != ENOENT)
9494
die_errno(_("Could not open commit-graph '%s'"), graph_name);

commit-graph.c

+19-28
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,21 @@
4444
/* Remember to update object flag allocation in object.h */
4545
#define REACHABLE (1u<<15)
4646

47-
char *get_commit_graph_filename(const char *obj_dir)
47+
char *get_commit_graph_filename(struct object_directory *odb)
4848
{
49-
char *filename = xstrfmt("%s/info/commit-graph", obj_dir);
50-
char *normalized = xmalloc(strlen(filename) + 1);
51-
normalize_path_copy(normalized, filename);
52-
free(filename);
53-
return normalized;
49+
return xstrfmt("%s/info/commit-graph", odb->path);
5450
}
5551

56-
static char *get_split_graph_filename(const char *obj_dir,
52+
static char *get_split_graph_filename(struct object_directory *odb,
5753
const char *oid_hex)
5854
{
59-
char *filename = xstrfmt("%s/info/commit-graphs/graph-%s.graph",
60-
obj_dir,
61-
oid_hex);
62-
char *normalized = xmalloc(strlen(filename) + 1);
63-
normalize_path_copy(normalized, filename);
64-
free(filename);
65-
return normalized;
55+
return xstrfmt("%s/info/commit-graphs/graph-%s.graph", odb->path,
56+
oid_hex);
6657
}
6758

68-
static char *get_chain_filename(const char *obj_dir)
59+
static char *get_chain_filename(struct object_directory *odb)
6960
{
70-
return xstrfmt("%s/info/commit-graphs/commit-graph-chain", obj_dir);
61+
return xstrfmt("%s/info/commit-graphs/commit-graph-chain", odb->path);
7162
}
7263

7364
static uint8_t oid_version(void)
@@ -330,7 +321,7 @@ static struct commit_graph *load_commit_graph_one(const char *graph_file)
330321
static struct commit_graph *load_commit_graph_v1(struct repository *r,
331322
struct object_directory *odb)
332323
{
333-
char *graph_name = get_commit_graph_filename(odb->path);
324+
char *graph_name = get_commit_graph_filename(odb);
334325
struct commit_graph *g = load_commit_graph_one(graph_name);
335326
free(graph_name);
336327

@@ -381,7 +372,7 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r,
381372
struct stat st;
382373
struct object_id *oids;
383374
int i = 0, valid = 1, count;
384-
char *chain_name = get_chain_filename(odb->path);
375+
char *chain_name = get_chain_filename(odb);
385376
FILE *fp;
386377
int stat_res;
387378

@@ -414,7 +405,7 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r,
414405

415406
valid = 0;
416407
for (odb = r->objects->odb; odb; odb = odb->next) {
417-
char *graph_name = get_split_graph_filename(odb->path, line.buf);
408+
char *graph_name = get_split_graph_filename(odb, line.buf);
418409
struct commit_graph *g = load_commit_graph_one(graph_name);
419410

420411
free(graph_name);
@@ -1375,7 +1366,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
13751366
ctx->odb->path);
13761367
ctx->graph_name = strbuf_detach(&tmp_file, NULL);
13771368
} else {
1378-
ctx->graph_name = get_commit_graph_filename(ctx->odb->path);
1369+
ctx->graph_name = get_commit_graph_filename(ctx->odb);
13791370
}
13801371

13811372
if (safe_create_leading_directories(ctx->graph_name)) {
@@ -1386,7 +1377,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
13861377
}
13871378

13881379
if (ctx->split) {
1389-
char *lock_name = get_chain_filename(ctx->odb->path);
1380+
char *lock_name = get_chain_filename(ctx->odb);
13901381

13911382
hold_lock_file_for_update(&lk, lock_name, LOCK_DIE_ON_ERROR);
13921383

@@ -1474,7 +1465,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
14741465

14751466
if (ctx->split && ctx->base_graph_name && ctx->num_commit_graphs_after > 1) {
14761467
char *new_base_hash = xstrdup(oid_to_hex(&ctx->new_base_graph->oid));
1477-
char *new_base_name = get_split_graph_filename(ctx->new_base_graph->odb->path, new_base_hash);
1468+
char *new_base_name = get_split_graph_filename(ctx->new_base_graph->odb, new_base_hash);
14781469

14791470
free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
14801471
free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2]);
@@ -1510,12 +1501,12 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
15101501
}
15111502
}
15121503
} else {
1513-
char *graph_name = get_commit_graph_filename(ctx->odb->path);
1504+
char *graph_name = get_commit_graph_filename(ctx->odb);
15141505
unlink(graph_name);
15151506
}
15161507

15171508
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(oid_to_hex(&file_hash));
1518-
final_graph_name = get_split_graph_filename(ctx->odb->path,
1509+
final_graph_name = get_split_graph_filename(ctx->odb,
15191510
ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
15201511
ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1] = final_graph_name;
15211512

@@ -1557,7 +1548,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
15571548

15581549
while (g && (g->num_commits <= size_mult * num_commits ||
15591550
(max_commits && num_commits > max_commits))) {
1560-
if (strcmp(g->odb->path, ctx->odb->path))
1551+
if (g->odb != ctx->odb)
15611552
break;
15621553

15631554
num_commits += g->num_commits;
@@ -1569,10 +1560,10 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
15691560
ctx->new_base_graph = g;
15701561

15711562
if (ctx->num_commit_graphs_after == 2) {
1572-
char *old_graph_name = get_commit_graph_filename(g->odb->path);
1563+
char *old_graph_name = get_commit_graph_filename(g->odb);
15731564

15741565
if (!strcmp(g->filename, old_graph_name) &&
1575-
strcmp(g->odb->path, ctx->odb->path)) {
1566+
g->odb != ctx->odb) {
15761567
ctx->num_commit_graphs_after = 1;
15771568
ctx->new_base_graph = NULL;
15781569
}
@@ -1723,7 +1714,7 @@ static void expire_commit_graphs(struct write_commit_graph_context *ctx)
17231714
if (ctx->split_opts && ctx->split_opts->expire_time)
17241715
expire_time -= ctx->split_opts->expire_time;
17251716
if (!ctx->split) {
1726-
char *chain_file_name = get_chain_filename(ctx->odb->path);
1717+
char *chain_file_name = get_chain_filename(ctx->odb);
17271718
unlink(chain_file_name);
17281719
free(chain_file_name);
17291720
ctx->num_commit_graphs_after = 0;

commit-graph.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
struct commit;
1414

15-
char *get_commit_graph_filename(const char *obj_dir);
15+
char *get_commit_graph_filename(struct object_directory *odb);
1616
int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
1717

1818
/*

t/helper/test-read-graph.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ int cmd__read_graph(int argc, const char **argv)
1111
int open_ok;
1212
int fd;
1313
struct stat st;
14-
const char *object_dir;
14+
struct object_directory *odb;
1515

1616
setup_git_directory();
17-
object_dir = get_object_directory();
17+
odb = the_repository->objects->odb;
1818

19-
graph_name = get_commit_graph_filename(object_dir);
19+
graph_name = get_commit_graph_filename(odb);
2020

2121
open_ok = open_commit_graph(graph_name, &fd, &st);
2222
if (!open_ok)

0 commit comments

Comments
 (0)