Skip to content

Commit 31f5b97

Browse files
pks-tgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ea194f9 commit 31f5b97

File tree

1 file changed

+63
-17
lines changed

1 file changed

+63
-17
lines changed

reftable/record.c

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
359359
uint64_t update_index = 0;
360360
const char *refname = NULL;
361361
size_t refname_cap = 0;
362-
int n;
362+
int n, err;
363363

364364
assert(hash_size > 0);
365365

@@ -375,6 +375,10 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
375375
SWAP(r->refname_cap, refname_cap);
376376

377377
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+
}
378382
memcpy(r->refname, key.buf, key.len);
379383
r->refname[key.len] = 0;
380384

@@ -383,7 +387,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
383387
switch (val_type) {
384388
case REFTABLE_REF_VAL1:
385389
if (in.len < hash_size) {
386-
return -1;
390+
err = REFTABLE_FORMAT_ERROR;
391+
goto done;
387392
}
388393

389394
memcpy(r->value.val1, in.buf, hash_size);
@@ -392,7 +397,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
392397

393398
case REFTABLE_REF_VAL2:
394399
if (in.len < 2 * hash_size) {
395-
return -1;
400+
err = REFTABLE_FORMAT_ERROR;
401+
goto done;
396402
}
397403

398404
memcpy(r->value.val2.value, in.buf, hash_size);
@@ -405,7 +411,8 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
405411
case REFTABLE_REF_SYMREF: {
406412
int n = decode_string(scratch, in);
407413
if (n < 0) {
408-
return -1;
414+
err = REFTABLE_FORMAT_ERROR;
415+
goto done;
409416
}
410417
string_view_consume(&in, n);
411418
r->value.symref = strbuf_detach(scratch, NULL);
@@ -419,6 +426,9 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
419426
}
420427

421428
return start.len - in.len;
429+
430+
done:
431+
return err;
422432
}
423433

424434
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,
552562
reftable_obj_record_release(r);
553563

554564
REFTABLE_ALLOC_ARRAY(r->hash_prefix, key.len);
565+
if (!r->hash_prefix)
566+
return REFTABLE_OUT_OF_MEMORY_ERROR;
555567
memcpy(r->hash_prefix, key.buf, key.len);
556568
r->hash_prefix_len = key.len;
557569

@@ -570,6 +582,8 @@ static int reftable_obj_record_decode(void *rec, struct strbuf key,
570582
return start.len - in.len;
571583

572584
REFTABLE_ALLOC_ARRAY(r->offsets, count);
585+
if (!r->offsets)
586+
return REFTABLE_OUT_OF_MEMORY_ERROR;
573587
r->offset_len = count;
574588

575589
n = get_var_int(&r->offsets[0], &in);
@@ -801,12 +815,17 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
801815
struct reftable_log_record *r = rec;
802816
uint64_t max = 0;
803817
uint64_t ts = 0;
804-
int n;
818+
int err, n;
805819

806820
if (key.len <= 9 || key.buf[key.len - 9] != 0)
807821
return REFTABLE_FORMAT_ERROR;
808822

809823
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+
810829
memcpy(r->refname, key.buf, key.len - 8);
811830
ts = get_be64(key.buf + key.len - 8);
812831

@@ -829,17 +848,21 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
829848
if (val_type == REFTABLE_LOG_DELETION)
830849
return 0;
831850

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+
}
834855

835856
memcpy(r->value.update.old_hash, in.buf, hash_size);
836857
memcpy(r->value.update.new_hash, in.buf + hash_size, hash_size);
837858

838859
string_view_consume(&in, 2 * hash_size);
839860

840861
n = decode_string(scratch, in);
841-
if (n < 0)
862+
if (n < 0) {
863+
err = REFTABLE_FORMAT_ERROR;
842864
goto done;
865+
}
843866
string_view_consume(&in, n);
844867

845868
/*
@@ -850,52 +873,75 @@ static int reftable_log_record_decode(void *rec, struct strbuf key,
850873
*/
851874
if (!r->value.update.name ||
852875
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;
855883
memcpy(r->value.update.name, scratch->buf, scratch->len);
856884
r->value.update.name[scratch->len] = 0;
857885
}
858886

859887
n = decode_string(scratch, in);
860-
if (n < 0)
888+
if (n < 0) {
889+
err = REFTABLE_FORMAT_ERROR;
861890
goto done;
891+
}
862892
string_view_consume(&in, n);
863893

864894
/* Same as above, but for the reflog email. */
865895
if (!r->value.update.email ||
866896
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;
869904
memcpy(r->value.update.email, scratch->buf, scratch->len);
870905
r->value.update.email[scratch->len] = 0;
871906
}
872907

873908
ts = 0;
874909
n = get_var_int(&ts, &in);
875-
if (n < 0)
910+
if (n < 0) {
911+
err = REFTABLE_FORMAT_ERROR;
876912
goto done;
913+
}
877914
string_view_consume(&in, n);
878915
r->value.update.time = ts;
879-
if (in.len < 2)
916+
if (in.len < 2) {
917+
err = REFTABLE_FORMAT_ERROR;
880918
goto done;
919+
}
881920

882921
r->value.update.tz_offset = get_be16(in.buf);
883922
string_view_consume(&in, 2);
884923

885924
n = decode_string(scratch, in);
886-
if (n < 0)
925+
if (n < 0) {
926+
err = REFTABLE_FORMAT_ERROR;
887927
goto done;
928+
}
888929
string_view_consume(&in, n);
889930

890931
REFTABLE_ALLOC_GROW(r->value.update.message, scratch->len + 1,
891932
r->value.update.message_cap);
933+
if (!r->value.update.message) {
934+
err = REFTABLE_OUT_OF_MEMORY_ERROR;
935+
goto done;
936+
}
937+
892938
memcpy(r->value.update.message, scratch->buf, scratch->len);
893939
r->value.update.message[scratch->len] = 0;
894940

895941
return start.len - in.len;
896942

897943
done:
898-
return REFTABLE_FORMAT_ERROR;
944+
return err;
899945
}
900946

901947
static int null_streq(const char *a, const char *b)

0 commit comments

Comments
 (0)