reftable/record: handle allocation failures when decoding records

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>

Patrick Steinhardt committed Oct 2, 2024 at 12:55 UTC 31f5b972e0231d4211987775dd58e67815734989
1 file changed +63 -17
reftable/record.c
+63 -17
@@ -359,7 +359,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
359 uint64_t update_index = 0;
360 const char *refname = NULL;
361 size_t refname_cap = 0;
362 - int n;
362 + int n, err;
363
364 assert(hash_size > 0);
365
@@ -375,6 +375,10 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
375 SWAP(r->refname_cap, refname_cap);
376
377 REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap);
378 + if (!r->refname) {
379 + err = REFTABLE_OUT_OF_MEMORY_ERROR;
380 + goto done;
381 + }
382 memcpy(r->refname, key.buf, key.len);
383 r->refname[key.len] = 0;
384
@@ -383,7 +387,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
387 switch (val_type) {
388 case REFTABLE_REF_VAL1:
389 if (in.len < hash_size) {
386 - return -1;
390 + err = REFTABLE_FORMAT_ERROR;
391 + goto done;
392 }
393
394 memcpy(r->value.val1, in.buf, hash_size);
@@ -392,7 +397,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
397
398 case REFTABLE_REF_VAL2:
399 if (in.len < 2 * hash_size) {
395 - return -1;
400 + err = REFTABLE_FORMAT_ERROR;
401 + goto done;
402 }
403
404 memcpy(r->value.val2.value, in.buf, hash_size);
@@ -405,7 +411,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
411 case REFTABLE_REF_SYMREF: {
412 int n = decode_string(scratch, in);
413 if (n < 0) {
408 - return -1;
414 + err = REFTABLE_FORMAT_ERROR;
415 + goto done;
416 }
417 string_view_consume(&in, n);
418 r->value.symref = strbuf_detach(scratch, NULL);
@@ -419,6 +426,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
426 }
427
428 return start.len - in.len;
429 +
430 +done:
431 + return err;
432 }
433
434 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,
562 reftable_obj_record_release(r);
563
564 REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
565 + if (!r->hash_prefix)
566 + return REFTABLE_OUT_OF_MEMORY_ERROR;
567 memcpy(r->hash_prefix, key.buf, key.len);
568 r->hash_prefix_len = key.len;
569
@@ -570,6 +582,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
582 return start.len - in.len;
583
584 REFTABLE_ALLOC_ARRAY(r->offsets, count);
585 + if (!r->offsets)
586 + return REFTABLE_OUT_OF_MEMORY_ERROR;
587 r->offset_len = count;
588
589 n = get_var_int(&r->offsets[0], &in);
@@ -801,12 +815,17 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
815 struct reftable_log_record *r = rec;
816 uint64_t max = 0;
817 uint64_t ts = 0;
804 - int n;
818 + int err, n;
819
820 if (key.len <= 9 || key.buf[key.len - 9] != 0)
821 return REFTABLE_FORMAT_ERROR;
822
823 REFTABLE_ALLOC_GROW(r->refname, key.len - 8, r->refname_cap);
824 + if (!r->refname) {
825 + err = REFTABLE_OUT_OF_MEMORY_ERROR;
826 + goto done;
827 + }
828 +
829 memcpy(r->refname, key.buf, key.len - 8);
830 ts = get_be64(key.buf + key.len - 8);
831
@@ -829,8 +848,10 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
848 if (val_type == REFTABLE_LOG_DELETION)
849 return 0;
850
832 - if (in.len < 2 * hash_size)
833 - return REFTABLE_FORMAT_ERROR;
851 + if (in.len < 2 * hash_size) {
852 + err = REFTABLE_FORMAT_ERROR;
853 + goto done;
854 + }
855
856 memcpy(r->value.update.old_hash, in.buf, hash_size);
857 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,
859 string_view_consume(&in, 2 * hash_size);
860
861 n = decode_string(scratch, in);
841 - if (n < 0)
862 + if (n < 0) {
863 + err = REFTABLE_FORMAT_ERROR;
864 goto done;
865 + }
866 string_view_consume(&in, n);
867
868 /*
@@ -850,52 +873,75 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
873 */
874 if (!r->value.update.name ||
875 strcmp(r->value.update.name, scratch->buf)) {
853 - r->value.update.name =
854 - reftable_realloc(r->value.update.name, scratch->len + 1);
876 + char *name = reftable_realloc(r->value.update.name, scratch->len + 1);
877 + if (!name) {
878 + err = REFTABLE_OUT_OF_MEMORY_ERROR;
879 + goto done;
880 + }
881 +
882 + r->value.update.name = name;
883 memcpy(r->value.update.name, scratch->buf, scratch->len);
884 r->value.update.name[scratch->len] = 0;
885 }
886
887 n = decode_string(scratch, in);
860 - if (n < 0)
888 + if (n < 0) {
889 + err = REFTABLE_FORMAT_ERROR;
890 goto done;
891 + }
892 string_view_consume(&in, n);
893
894 /* Same as above, but for the reflog email. */
895 if (!r->value.update.email ||
896 strcmp(r->value.update.email, scratch->buf)) {
867 - r->value.update.email =
868 - reftable_realloc(r->value.update.email, scratch->len + 1);
897 + char *email = reftable_realloc(r->value.update.email, scratch->len + 1);
898 + if (!email) {
899 + err = REFTABLE_OUT_OF_MEMORY_ERROR;
900 + goto done;
901 + }
902 +
903 + r->value.update.email = email;
904 memcpy(r->value.update.email, scratch->buf, scratch->len);
905 r->value.update.email[scratch->len] = 0;
906 }
907
908 ts = 0;
909 n = get_var_int(&ts, &in);
875 - if (n < 0)
910 + if (n < 0) {
911 + err = REFTABLE_FORMAT_ERROR;
912 goto done;
913 + }
914 string_view_consume(&in, n);
915 r->value.update.time = ts;
879 - if (in.len < 2)
916 + if (in.len < 2) {
917 + err = REFTABLE_FORMAT_ERROR;
918 goto done;
919 + }
920
921 r->value.update.tz_offset = get_be16(in.buf);
922 string_view_consume(&in, 2);
923
924 n = decode_string(scratch, in);
886 - if (n < 0)
925 + if (n < 0) {
926 + err = REFTABLE_FORMAT_ERROR;
927 goto done;
928 + }
929 string_view_consume(&in, n);
930
931 REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1,
932 r->value.update.message_cap);
933 + if (!r->value.update.message) {
934 + err = REFTABLE_OUT_OF_MEMORY_ERROR;
935 + goto done;
936 + }
937 +
938 memcpy(r->value.update.message, scratch->buf, scratch->len);
939 r->value.update.message[scratch->len] = 0;
940
941 return start.len - in.len;
942
943 done:
898 - return REFTABLE_FORMAT_ERROR;
944 + return err;
945 }
946
947 static int null_streq(const char *a, const char *b)