]> git.ipfire.org Git - thirdparty/git.git/commitdiff
reftable/record: handle allocation failures when decoding records
authorPatrick Steinhardt <ps@pks.im>
Wed, 2 Oct 2024 10:55:43 +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 decoding records. While at it, fix some
error codes to be `REFTABLE_FORMAT_ERROR`.

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

index 60fd33c9c94b366b48e6146affe747704823f3f4..787e134c9a0491fffb584656f31f84494d6d10d5 100644 (file)
@@ -359,7 +359,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
        uint64_t update_index = 0;
        const char *refname = NULL;
        size_t refname_cap = 0;
-       int n;
+       int n, err;
 
        assert(hash_size > 0);
 
@@ -375,6 +375,10 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
        SWAP(r->refname_cap, refname_cap);
 
        REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap);
+       if (!r->refname) {
+               err = REFTABLE_OUT_OF_MEMORY_ERROR;
+               goto done;
+       }
        memcpy(r->refname, key.buf, key.len);
        r->refname[key.len] = 0;
 
@@ -383,7 +387,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
        switch (val_type) {
        case REFTABLE_REF_VAL1:
                if (in.len < hash_size) {
-                       return -1;
+                       err = REFTABLE_FORMAT_ERROR;
+                       goto done;
                }
 
                memcpy(r->value.val1, in.buf, hash_size);
@@ -392,7 +397,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
 
        case REFTABLE_REF_VAL2:
                if (in.len < 2 * hash_size) {
-                       return -1;
+                       err = REFTABLE_FORMAT_ERROR;
+                       goto done;
                }
 
                memcpy(r->value.val2.value, in.buf, hash_size);
@@ -405,7 +411,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
        case REFTABLE_REF_SYMREF: {
                int n = decode_string(scratch, in);
                if (n < 0) {
-                       return -1;
+                       err = REFTABLE_FORMAT_ERROR;
+                       goto done;
                }
                string_view_consume(&in, n);
                r->value.symref = strbuf_detach(scratch, NULL);
@@ -419,6 +426,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
        }
 
        return start.len - in.len;
+
+done:
+       return err;
 }
 
 static int reftable_ref_record_is_deletion_void(const void *p)
@@ -552,6 +562,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
        reftable_obj_record_release(r);
 
        REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
+       if (!r->hash_prefix)
+               return REFTABLE_OUT_OF_MEMORY_ERROR;
        memcpy(r->hash_prefix, key.buf, key.len);
        r->hash_prefix_len = key.len;
 
@@ -570,6 +582,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
                return start.len - in.len;
 
        REFTABLE_ALLOC_ARRAY(r->offsets, count);
+       if (!r->offsets)
+               return REFTABLE_OUT_OF_MEMORY_ERROR;
        r->offset_len = count;
 
        n = get_var_int(&r->offsets[0], &in);
@@ -801,12 +815,17 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
        struct reftable_log_record *r = rec;
        uint64_t max = 0;
        uint64_t ts = 0;
-       int n;
+       int err, n;
 
        if (key.len <= 9 || key.buf[key.len - 9] != 0)
                return REFTABLE_FORMAT_ERROR;
 
        REFTABLE_ALLOC_GROW(r->refname, key.len - 8, r->refname_cap);
+       if (!r->refname) {
+               err = REFTABLE_OUT_OF_MEMORY_ERROR;
+               goto done;
+       }
+
        memcpy(r->refname, key.buf, key.len - 8);
        ts = get_be64(key.buf + key.len - 8);
 
@@ -829,8 +848,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
        if (val_type == REFTABLE_LOG_DELETION)
                return 0;
 
-       if (in.len < 2 * hash_size)
-               return REFTABLE_FORMAT_ERROR;
+       if (in.len < 2 * hash_size) {
+               err = REFTABLE_FORMAT_ERROR;
+               goto done;
+       }
 
        memcpy(r->value.update.old_hash, in.buf, hash_size);
        memcpy(r->value.update.new_hash, in.buf + hash_size, hash_size);
@@ -838,8 +859,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
        string_view_consume(&in, 2 * hash_size);
 
        n = decode_string(scratch, in);
-       if (n < 0)
+       if (n < 0) {
+               err = REFTABLE_FORMAT_ERROR;
                goto done;
+       }
        string_view_consume(&in, n);
 
        /*
@@ -850,52 +873,75 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
         */
        if (!r->value.update.name ||
            strcmp(r->value.update.name, scratch->buf)) {
-               r->value.update.name =
-                       reftable_realloc(r->value.update.name, scratch->len + 1);
+               char *name = reftable_realloc(r->value.update.name, scratch->len + 1);
+               if (!name) {
+                       err = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto done;
+               }
+
+               r->value.update.name = name;
                memcpy(r->value.update.name, scratch->buf, scratch->len);
                r->value.update.name[scratch->len] = 0;
        }
 
        n = decode_string(scratch, in);
-       if (n < 0)
+       if (n < 0) {
+               err = REFTABLE_FORMAT_ERROR;
                goto done;
+       }
        string_view_consume(&in, n);
 
        /* Same as above, but for the reflog email. */
        if (!r->value.update.email ||
            strcmp(r->value.update.email, scratch->buf)) {
-               r->value.update.email =
-                       reftable_realloc(r->value.update.email, scratch->len + 1);
+               char *email = reftable_realloc(r->value.update.email, scratch->len + 1);
+               if (!email) {
+                       err = REFTABLE_OUT_OF_MEMORY_ERROR;
+                       goto done;
+               }
+
+               r->value.update.email = email;
                memcpy(r->value.update.email, scratch->buf, scratch->len);
                r->value.update.email[scratch->len] = 0;
        }
 
        ts = 0;
        n = get_var_int(&ts, &in);
-       if (n < 0)
+       if (n < 0) {
+               err = REFTABLE_FORMAT_ERROR;
                goto done;
+       }
        string_view_consume(&in, n);
        r->value.update.time = ts;
-       if (in.len < 2)
+       if (in.len < 2) {
+               err = REFTABLE_FORMAT_ERROR;
                goto done;
+       }
 
        r->value.update.tz_offset = get_be16(in.buf);
        string_view_consume(&in, 2);
 
        n = decode_string(scratch, in);
-       if (n < 0)
+       if (n < 0) {
+               err = REFTABLE_FORMAT_ERROR;
                goto done;
+       }
        string_view_consume(&in, n);
 
        REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1,
                            r->value.update.message_cap);
+       if (!r->value.update.message) {
+               err = REFTABLE_OUT_OF_MEMORY_ERROR;
+               goto done;
+       }
+
        memcpy(r->value.update.message, scratch->buf, scratch->len);
        r->value.update.message[scratch->len] = 0;
 
        return start.len - in.len;
 
 done:
-       return REFTABLE_FORMAT_ERROR;
+       return err;
 }
 
 static int null_streq(const char *a, const char *b)