reftable/writer: handle allocation failures in `writer_index_hash()`

Handle allocation errors in `writer_index_hash()`. Adjust its only caller in `reftable_writer_add_ref()` accordingly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Oct 2, 2024 at 12:55 UTC b680af2dba27f851d3cea2000094a1dc42f38cd2
1 file changed +38 -23
reftable/writer.c
+38 -23
@@ -186,18 +186,22 @@ static int obj_index_tree_node_compare(const void *a, const void *b)
186 &((const struct obj_index_tree_node *)b)->hash);
187 }
188
189 -static void writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
189 +static int writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
190 {
191 uint64_t off = w->next;
192 -
192 struct obj_index_tree_node want = { .hash = *hash };
193 + struct obj_index_tree_node *key;
194 + struct tree_node *node;
195
195 - struct tree_node *node = tree_search(&want, &w->obj_index_tree,
196 - &obj_index_tree_node_compare, 0);
197 - struct obj_index_tree_node *key = NULL;
196 + node = tree_search(&want, &w->obj_index_tree,
197 + &obj_index_tree_node_compare, 0);
198 if (!node) {
199 struct obj_index_tree_node empty = OBJ_INDEX_TREE_NODE_INIT;
200 - key = reftable_malloc(sizeof(struct obj_index_tree_node));
200 +
201 + key = reftable_malloc(sizeof(*key));
202 + if (!key)
203 + return REFTABLE_OUT_OF_MEMORY_ERROR;
204 +
205 *key = empty;
206
207 strbuf_reset(&key->hash);
@@ -208,12 +212,15 @@ static void writer_index_hash(struct reftable_writer *w, struct strbuf *hash)
212 key = node->key;
213 }
214
211 - if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off) {
212 - return;
213 - }
215 + if (key->offset_len > 0 && key->offsets[key->offset_len - 1] == off)
216 + return 0;
217
218 REFTABLE_ALLOC_GROW(key->offsets, key->offset_len + 1, key->offset_cap);
219 + if (!key->offsets)
220 + return REFTABLE_OUT_OF_MEMORY_ERROR;
221 key->offsets[key->offset_len++] = off;
222 +
223 + return 0;
224 }
225
226 static int writer_add_record(struct reftable_writer *w,
@@ -284,11 +291,11 @@ int reftable_writer_add_ref(struct reftable_writer *w,
291 .ref = *ref
292 },
293 };
287 - int err = 0;
294 + struct strbuf buf = STRBUF_INIT;
295 + int err;
296
289 - if (!ref->refname)
290 - return REFTABLE_API_ERROR;
291 - if (ref->update_index < w->min_update_index ||
297 + if (!ref->refname ||
298 + ref->update_index < w->min_update_index ||
299 ref->update_index > w->max_update_index)
300 return REFTABLE_API_ERROR;
301
@@ -296,24 +303,32 @@ int reftable_writer_add_ref(struct reftable_writer *w,
303
304 err = writer_add_record(w, &rec);
305 if (err < 0)
299 - return err;
306 + goto out;
307
308 if (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {
302 - struct strbuf h = STRBUF_INIT;
303 - strbuf_add(&h, (char *)reftable_ref_record_val1(ref),
309 + strbuf_add(&buf, (char *)reftable_ref_record_val1(ref),
310 hash_size(w->opts.hash_id));
305 - writer_index_hash(w, &h);
306 - strbuf_release(&h);
311 +
312 + err = writer_index_hash(w, &buf);
313 + if (err < 0)
314 + goto out;
315 }
316
317 if (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {
310 - struct strbuf h = STRBUF_INIT;
311 - strbuf_add(&h, reftable_ref_record_val2(ref),
318 + strbuf_reset(&buf);
319 + strbuf_add(&buf, reftable_ref_record_val2(ref),
320 hash_size(w->opts.hash_id));
313 - writer_index_hash(w, &h);
314 - strbuf_release(&h);
321 +
322 + err = writer_index_hash(w, &buf);
323 + if (err < 0)
324 + goto out;
325 }
316 - return 0;
326 +
327 + err = 0;
328 +
329 +out:
330 + strbuf_release(&buf);
331 + return err;
332 }
333
334 int reftable_writer_add_refs(struct reftable_writer *w,