reftable/record: stop using `BUG()` in `reftable_record_init()`

We're aborting the program via `BUG()` in case `reftable_record_init()` was invoked with an unknown record type. This is bad because we may now die in library code, and because it makes us depend on the Git codebase. Refactor the code such that `reftable_record_init()` can return an error code to the caller. Adapt any callers accordingly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Feb 18, 2025 at 10:20 UTC 9d9fac0f34ec47cc6eafeb3e10378ab8f3310346
7 files changed +21 -13
reftable/block.c
+3 -1
@@ -508,7 +508,9 @@ int block_iter_seek_key(struct block_iter *it, const struct block_reader *br,
508 it->block_len = br->block_len;
509 it->hash_size = br->hash_size;
510
511 - reftable_record_init(&rec, block_reader_type(br));
511 + err = reftable_record_init(&rec, block_reader_type(br));
512 + if (err < 0)
513 + goto done;
514
515 /*
516 * We're looking for the last entry less than the wanted key so that
reftable/merged.c
+4 -1
@@ -253,7 +253,10 @@ int merged_table_init_iter(struct reftable_merged_table *mt,
253 }
254
255 for (size_t i = 0; i < mt->readers_len; i++) {
256 - reftable_record_init(&subiters[i].rec, typ);
256 + ret = reftable_record_init(&subiters[i].rec, typ);
257 + if (ret < 0)
258 + goto out;
259 +
260 ret = reader_init_iter(mt->readers[i], &subiters[i].iter, typ);
261 if (ret < 0)
262 goto out;
reftable/reader.c
+4 -1
@@ -360,7 +360,10 @@ static int table_iter_seek_linear(struct table_iter *ti,
360 struct reftable_record rec;
361 int err;
362
363 - reftable_record_init(&rec, reftable_record_type(want));
363 + err = reftable_record_init(&rec, reftable_record_type(want));
364 + if (err < 0)
365 + goto done;
366 +
367 err = reftable_record_key(want, &want_key);
368 if (err < 0)
369 goto done;
reftable/record.c
+4 -4
@@ -1306,7 +1306,7 @@ reftable_record_vtable(struct reftable_record *rec)
1306 abort();
1307 }
1308
1309 -void reftable_record_init(struct reftable_record *rec, uint8_t typ)
1309 +int reftable_record_init(struct reftable_record *rec, uint8_t typ)
1310 {
1311 memset(rec, 0, sizeof(*rec));
1312 rec->type = typ;
@@ -1315,11 +1315,11 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ)
1315 case BLOCK_TYPE_REF:
1316 case BLOCK_TYPE_LOG:
1317 case BLOCK_TYPE_OBJ:
1318 - return;
1318 + return 0;
1319 case BLOCK_TYPE_INDEX:
1320 reftable_buf_init(&rec->u.idx.last_key);
1321 - return;
1321 + return 0;
1322 default:
1323 - BUG("unhandled record type");
1323 + return REFTABLE_API_ERROR;
1324 }
1325 }
reftable/record.h
+2 -2
@@ -130,8 +130,8 @@ struct reftable_record {
130 } u;
131 };
132
133 -/* Initialize the reftable record for the given type */
134 -void reftable_record_init(struct reftable_record *rec, uint8_t typ);
133 +/* Initialize the reftable record for the given type. */
134 +int reftable_record_init(struct reftable_record *rec, uint8_t typ);
135
136 /* see struct record_vtable */
137 int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
t/unit-tests/t-reftable-pq.c
+3 -3
@@ -32,7 +32,7 @@ static void t_pq_record(void)
32 char *last = NULL;
33
34 for (i = 0; i < N; i++) {
35 - reftable_record_init(&recs[i], BLOCK_TYPE_REF);
35 + check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
36 recs[i].u.ref.refname = xstrfmt("%02"PRIuMAX, (uintmax_t)i);
37 }
38
@@ -72,7 +72,7 @@ static void t_pq_index(void)
72 size_t N = ARRAY_SIZE(recs), i;
73
74 for (i = 0; i < N; i++) {
75 - reftable_record_init(&recs[i], BLOCK_TYPE_REF);
75 + check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
76 recs[i].u.ref.refname = (char *) "refs/heads/master";
77 }
78
@@ -111,7 +111,7 @@ static void t_merged_iter_pqueue_top(void)
111 size_t N = ARRAY_SIZE(recs), i;
112
113 for (i = 0; i < N; i++) {
114 - reftable_record_init(&recs[i], BLOCK_TYPE_REF);
114 + check(!reftable_record_init(&recs[i], BLOCK_TYPE_REF));
115 recs[i].u.ref.refname = (char *) "refs/heads/master";
116 }
117
t/unit-tests/t-reftable-record.c
+1 -1
@@ -17,7 +17,7 @@ static void t_copy(struct reftable_record *rec)
17 uint8_t typ;
18
19 typ = reftable_record_type(rec);
20 - reftable_record_init(&copy, typ);
20 + check(!reftable_record_init(&copy, typ));
21 reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1);
22 /* do it twice to catch memory leaks */
23 reftable_record_copy_from(&copy, rec, REFTABLE_HASH_SIZE_SHA1);