]> git.ipfire.org Git - thirdparty/git.git/commitdiff
reftable/record: handle allocation failures on copy
authorPatrick Steinhardt <ps@pks.im>
Wed, 2 Oct 2024 10:55:40 +0000 (12:55 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Oct 2024 14:53:52 +0000 (07:53 -0700)
Handle allocation failures when copying records. While at it, convert
from `xstrdup()` to `reftable_strdup()`. Adapt callsites to check for
error codes.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
reftable/record.c
reftable/record.h

index 6b5a075b921062caee58f63262e20399b2678b7e..60fd33c9c94b366b48e6146affe747704823f3f4 100644 (file)
@@ -215,13 +215,14 @@ static void reftable_ref_record_key(const void *r, struct strbuf *dest)
        strbuf_addstr(dest, rec->refname);
 }
 
-static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
-                                         int hash_size)
+static int reftable_ref_record_copy_from(void *rec, const void *src_rec,
+                                        int hash_size)
 {
        struct reftable_ref_record *ref = rec;
        const struct reftable_ref_record *src = src_rec;
        char *refname = NULL;
        size_t refname_cap = 0;
+       int err;
 
        assert(hash_size > 0);
 
@@ -236,6 +237,11 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
 
                REFTABLE_ALLOC_GROW(ref->refname, refname_len + 1,
                                    ref->refname_cap);
+               if (!ref->refname) {
+                       err = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto out;
+               }
+
                memcpy(ref->refname, src->refname, refname_len);
                ref->refname[refname_len] = 0;
        }
@@ -254,9 +260,17 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
                       src->value.val2.target_value, hash_size);
                break;
        case REFTABLE_REF_SYMREF:
-               ref->value.symref = xstrdup(src->value.symref);
+               ref->value.symref = reftable_strdup(src->value.symref);
+               if (!ref->value.symref) {
+                       err = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto out;
+               }
                break;
        }
+
+       err = 0;
+out:
+       return err;
 }
 
 static void reftable_ref_record_release_void(void *rec)
@@ -457,23 +471,28 @@ static void reftable_obj_record_release(void *rec)
        memset(obj, 0, sizeof(struct reftable_obj_record));
 }
 
-static void reftable_obj_record_copy_from(void *rec, const void *src_rec,
-                                         int hash_size UNUSED)
+static int reftable_obj_record_copy_from(void *rec, const void *src_rec,
+                                        int hash_size UNUSED)
 {
        struct reftable_obj_record *obj = rec;
-       const struct reftable_obj_record *src =
-               (const struct reftable_obj_record *)src_rec;
+       const struct reftable_obj_record *src = src_rec;
 
        reftable_obj_record_release(obj);
 
        REFTABLE_ALLOC_ARRAY(obj->hash_prefix, src->hash_prefix_len);
+       if (!obj->hash_prefix)
+               return REFTABLE_OUT_OF_MEMORY_ERROR;
        obj->hash_prefix_len = src->hash_prefix_len;
        if (src->hash_prefix_len)
                memcpy(obj->hash_prefix, src->hash_prefix, obj->hash_prefix_len);
 
        REFTABLE_ALLOC_ARRAY(obj->offsets, src->offset_len);
+       if (!obj->offsets)
+               return REFTABLE_OUT_OF_MEMORY_ERROR;
        obj->offset_len = src->offset_len;
        COPY_ARRAY(obj->offsets, src->offsets, src->offset_len);
+
+       return 0;
 }
 
 static uint8_t reftable_obj_record_val_type(const void *rec)
@@ -646,33 +665,44 @@ static void reftable_log_record_key(const void *r, struct strbuf *dest)
        strbuf_add(dest, i64, sizeof(i64));
 }
 
-static void reftable_log_record_copy_from(void *rec, const void *src_rec,
-                                         int hash_size)
+static int reftable_log_record_copy_from(void *rec, const void *src_rec,
+                                        int hash_size)
 {
        struct reftable_log_record *dst = rec;
        const struct reftable_log_record *src =
                (const struct reftable_log_record *)src_rec;
+       int ret;
 
        reftable_log_record_release(dst);
        *dst = *src;
+
        if (dst->refname) {
-               dst->refname = xstrdup(dst->refname);
+               dst->refname = reftable_strdup(dst->refname);
+               if (!dst->refname) {
+                       ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto out;
+               }
        }
+
        switch (dst->value_type) {
        case REFTABLE_LOG_DELETION:
                break;
        case REFTABLE_LOG_UPDATE:
-               if (dst->value.update.email) {
+               if (dst->value.update.email)
                        dst->value.update.email =
-                               xstrdup(dst->value.update.email);
-               }
-               if (dst->value.update.name) {
+                               reftable_strdup(dst->value.update.email);
+               if (dst->value.update.name)
                        dst->value.update.name =
-                               xstrdup(dst->value.update.name);
-               }
-               if (dst->value.update.message) {
+                               reftable_strdup(dst->value.update.name);
+               if (dst->value.update.message)
                        dst->value.update.message =
-                               xstrdup(dst->value.update.message);
+                               reftable_strdup(dst->value.update.message);
+
+               if (!dst->value.update.email ||
+                   !dst->value.update.name ||
+                   !dst->value.update.message) {
+                       ret = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto out;
                }
 
                memcpy(dst->value.update.new_hash,
@@ -681,6 +711,10 @@ static void reftable_log_record_copy_from(void *rec, const void *src_rec,
                       src->value.update.old_hash, hash_size);
                break;
        }
+
+       ret = 0;
+out:
+       return ret;
 }
 
 static void reftable_log_record_release_void(void *rec)
@@ -954,8 +988,8 @@ static void reftable_index_record_key(const void *r, struct strbuf *dest)
        strbuf_addbuf(dest, &rec->last_key);
 }
 
-static void reftable_index_record_copy_from(void *rec, const void *src_rec,
-                                           int hash_size UNUSED)
+static int reftable_index_record_copy_from(void *rec, const void *src_rec,
+                                          int hash_size UNUSED)
 {
        struct reftable_index_record *dst = rec;
        const struct reftable_index_record *src = src_rec;
@@ -963,6 +997,8 @@ static void reftable_index_record_copy_from(void *rec, const void *src_rec,
        strbuf_reset(&dst->last_key);
        strbuf_addbuf(&dst->last_key, &src->last_key);
        dst->offset = src->offset;
+
+       return 0;
 }
 
 static void reftable_index_record_release(void *rec)
@@ -1054,14 +1090,14 @@ int reftable_record_encode(struct reftable_record *rec, struct string_view dest,
                                                   dest, hash_size);
 }
 
-void reftable_record_copy_from(struct reftable_record *rec,
+int reftable_record_copy_from(struct reftable_record *rec,
                               struct reftable_record *src, int hash_size)
 {
        assert(src->type == rec->type);
 
-       reftable_record_vtable(rec)->copy_from(reftable_record_data(rec),
-                                              reftable_record_data(src),
-                                              hash_size);
+       return reftable_record_vtable(rec)->copy_from(reftable_record_data(rec),
+                                                     reftable_record_data(src),
+                                                     hash_size);
 }
 
 uint8_t reftable_record_val_type(struct reftable_record *rec)
index 5003bacdb0c21ede864693b60fec91e2e62b1727..0f53ba54434ff024fb71dea4d98e01fe1d3f2266 100644 (file)
@@ -44,7 +44,7 @@ struct reftable_record_vtable {
        /* The record type of ('r' for ref). */
        uint8_t type;
 
-       void (*copy_from)(void *dest, const void *src, int hash_size);
+       int (*copy_from)(void *dest, const void *src, int hash_size);
 
        /* a value of [0..7], indicating record subvariants (eg. ref vs. symref
         * vs ref deletion) */
@@ -137,8 +137,8 @@ void reftable_record_init(struct reftable_record *rec, uint8_t typ);
 int reftable_record_cmp(struct reftable_record *a, struct reftable_record *b);
 int reftable_record_equal(struct reftable_record *a, struct reftable_record *b, int hash_size);
 void reftable_record_key(struct reftable_record *rec, struct strbuf *dest);
-void reftable_record_copy_from(struct reftable_record *rec,
-                              struct reftable_record *src, int hash_size);
+int reftable_record_copy_from(struct reftable_record *rec,
+                             struct reftable_record *src, int hash_size);
 uint8_t reftable_record_val_type(struct reftable_record *rec);
 int reftable_record_encode(struct reftable_record *rec, struct string_view dest,
                           int hash_size);