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)