Skip to content

Commit 2d5dbb3

Browse files
pks-tgitster
authored andcommitted
reftable/block: handle allocation failures
Handle allocation failures in `block_writer_init()` and `block_reader_init()`. This requires us to bubble up error codes into `writer_reinit_block_writer()`. Adapt call sites accordingly. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cd6a471 commit 2d5dbb3

File tree

4 files changed

+69
-29
lines changed

4 files changed

+69
-29
lines changed

reftable/block.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
5252
return -1;
5353
if (is_restart) {
5454
REFTABLE_ALLOC_GROW(w->restarts, w->restart_len + 1, w->restart_cap);
55+
if (!w->restarts)
56+
return REFTABLE_OUT_OF_MEMORY_ERROR;
5557
w->restarts[w->restart_len++] = w->next;
5658
}
5759

@@ -63,8 +65,8 @@ static int block_writer_register_restart(struct block_writer *w, int n,
6365
return 0;
6466
}
6567

66-
void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
67-
uint32_t block_size, uint32_t header_off, int hash_size)
68+
int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
69+
uint32_t block_size, uint32_t header_off, int hash_size)
6870
{
6971
bw->buf = buf;
7072
bw->hash_size = hash_size;
@@ -78,8 +80,12 @@ void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
7880
bw->last_key.len = 0;
7981
if (!bw->zstream) {
8082
REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
83+
if (!bw->zstream)
84+
return REFTABLE_OUT_OF_MEMORY_ERROR;
8185
deflateInit(bw->zstream, 9);
8286
}
87+
88+
return 0;
8389
}
8490

8591
uint8_t block_writer_type(struct block_writer *bw)
@@ -163,6 +169,10 @@ int block_writer_finish(struct block_writer *w)
163169
*/
164170
compressed_len = deflateBound(w->zstream, src_len);
165171
REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap);
172+
if (!w->compressed) {
173+
ret = REFTABLE_OUT_OF_MEMORY_ERROR;
174+
return ret;
175+
}
166176

167177
w->zstream->next_out = w->compressed;
168178
w->zstream->avail_out = compressed_len;
@@ -219,12 +229,21 @@ int block_reader_init(struct block_reader *br, struct reftable_block *block,
219229
/* Log blocks specify the *uncompressed* size in their header. */
220230
REFTABLE_ALLOC_GROW(br->uncompressed_data, sz,
221231
br->uncompressed_cap);
232+
if (!br->uncompressed_data) {
233+
err = REFTABLE_OUT_OF_MEMORY_ERROR;
234+
goto done;
235+
}
222236

223237
/* Copy over the block header verbatim. It's not compressed. */
224238
memcpy(br->uncompressed_data, block->data, block_header_skip);
225239

226240
if (!br->zstream) {
227241
REFTABLE_CALLOC_ARRAY(br->zstream, 1);
242+
if (!br->zstream) {
243+
err = REFTABLE_OUT_OF_MEMORY_ERROR;
244+
goto done;
245+
}
246+
228247
err = inflateInit(br->zstream);
229248
} else {
230249
err = inflateReset(br->zstream);

reftable/block.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ struct block_writer {
4545
/*
4646
* initializes the blockwriter to write `typ` entries, using `buf` as temporary
4747
* storage. `buf` is not owned by the block_writer. */
48-
void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
49-
uint32_t block_size, uint32_t header_off, int hash_size);
48+
int block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
49+
uint32_t block_size, uint32_t header_off, int hash_size);
5050

5151
/* returns the block type (eg. 'r' for ref records. */
5252
uint8_t block_writer_type(struct block_writer *bw);

reftable/writer.c

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,24 @@ static int writer_write_header(struct reftable_writer *w, uint8_t *dest)
102102
return header_size(writer_version(w));
103103
}
104104

105-
static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
105+
static int writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
106106
{
107-
int block_start = 0;
108-
if (w->next == 0) {
107+
int block_start = 0, ret;
108+
109+
if (w->next == 0)
109110
block_start = header_size(writer_version(w));
110-
}
111111

112112
strbuf_reset(&w->last_key);
113-
block_writer_init(&w->block_writer_data, typ, w->block,
114-
w->opts.block_size, block_start,
115-
hash_size(w->opts.hash_id));
113+
ret = block_writer_init(&w->block_writer_data, typ, w->block,
114+
w->opts.block_size, block_start,
115+
hash_size(w->opts.hash_id));
116+
if (ret < 0)
117+
return ret;
118+
116119
w->block_writer = &w->block_writer_data;
117120
w->block_writer->restart_interval = w->opts.restart_interval;
121+
122+
return 0;
118123
}
119124

120125
int reftable_writer_new(struct reftable_writer **out,
@@ -247,8 +252,11 @@ static int writer_add_record(struct reftable_writer *w,
247252

248253
strbuf_reset(&w->last_key);
249254
strbuf_addbuf(&w->last_key, &key);
250-
if (!w->block_writer)
251-
writer_reinit_block_writer(w, reftable_record_type(rec));
255+
if (!w->block_writer) {
256+
err = writer_reinit_block_writer(w, reftable_record_type(rec));
257+
if (err < 0)
258+
goto done;
259+
}
252260

253261
if (block_writer_type(w->block_writer) != reftable_record_type(rec))
254262
BUG("record of type %d added to writer of type %d",
@@ -271,7 +279,9 @@ static int writer_add_record(struct reftable_writer *w,
271279
err = writer_flush_block(w);
272280
if (err < 0)
273281
goto done;
274-
writer_reinit_block_writer(w, reftable_record_type(rec));
282+
err = writer_reinit_block_writer(w, reftable_record_type(rec));
283+
if (err < 0)
284+
goto done;
275285

276286
/*
277287
* Try to add the record to the writer again. If this still fails then
@@ -461,7 +471,9 @@ static int writer_finish_section(struct reftable_writer *w)
461471

462472
max_level++;
463473
index_start = w->next;
464-
writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
474+
err = writer_reinit_block_writer(w, BLOCK_TYPE_INDEX);
475+
if (err < 0)
476+
return err;
465477

466478
idx = w->index;
467479
idx_len = w->index_len;
@@ -555,7 +567,10 @@ static void write_object_record(void *void_arg, void *key)
555567
if (arg->err < 0)
556568
goto done;
557569

558-
writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
570+
arg->err = writer_reinit_block_writer(arg->w, BLOCK_TYPE_OBJ);
571+
if (arg->err < 0)
572+
goto done;
573+
559574
arg->err = block_writer_add(arg->w->block_writer, &rec);
560575
if (arg->err == 0)
561576
goto done;
@@ -584,16 +599,18 @@ static int writer_dump_object_index(struct reftable_writer *w)
584599
struct common_prefix_arg common = {
585600
.max = 1, /* obj_id_len should be >= 2. */
586601
};
587-
if (w->obj_index_tree) {
602+
int err;
603+
604+
if (w->obj_index_tree)
588605
infix_walk(w->obj_index_tree, &update_common, &common);
589-
}
590606
w->stats.object_id_len = common.max + 1;
591607

592-
writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
608+
err = writer_reinit_block_writer(w, BLOCK_TYPE_OBJ);
609+
if (err < 0)
610+
return err;
593611

594-
if (w->obj_index_tree) {
612+
if (w->obj_index_tree)
595613
infix_walk(w->obj_index_tree, &write_object_record, &closure);
596-
}
597614

598615
if (closure.err < 0)
599616
return closure.err;

t/unit-tests/t-reftable-block.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ static void t_ref_block_read_write(void)
3434
REFTABLE_CALLOC_ARRAY(block.data, block_size);
3535
block.len = block_size;
3636
block_source_from_strbuf(&block.source ,&buf);
37-
block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
38-
header_off, hash_size(GIT_SHA1_FORMAT_ID));
37+
ret = block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size,
38+
header_off, hash_size(GIT_SHA1_FORMAT_ID));
39+
check(!ret);
3940

4041
rec.u.ref.refname = (char *) "";
4142
rec.u.ref.value_type = REFTABLE_REF_DELETION;
@@ -126,8 +127,9 @@ static void t_log_block_read_write(void)
126127
REFTABLE_CALLOC_ARRAY(block.data, block_size);
127128
block.len = block_size;
128129
block_source_from_strbuf(&block.source ,&buf);
129-
block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
130-
header_off, hash_size(GIT_SHA1_FORMAT_ID));
130+
ret = block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size,
131+
header_off, hash_size(GIT_SHA1_FORMAT_ID));
132+
check(!ret);
131133

132134
for (i = 0; i < N; i++) {
133135
rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i);
@@ -214,8 +216,9 @@ static void t_obj_block_read_write(void)
214216
REFTABLE_CALLOC_ARRAY(block.data, block_size);
215217
block.len = block_size;
216218
block_source_from_strbuf(&block.source, &buf);
217-
block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
218-
header_off, hash_size(GIT_SHA1_FORMAT_ID));
219+
ret = block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size,
220+
header_off, hash_size(GIT_SHA1_FORMAT_ID));
221+
check(!ret);
219222

220223
for (i = 0; i < N; i++) {
221224
uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated;
@@ -296,8 +299,9 @@ static void t_index_block_read_write(void)
296299
REFTABLE_CALLOC_ARRAY(block.data, block_size);
297300
block.len = block_size;
298301
block_source_from_strbuf(&block.source, &buf);
299-
block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
300-
header_off, hash_size(GIT_SHA1_FORMAT_ID));
302+
ret = block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size,
303+
header_off, hash_size(GIT_SHA1_FORMAT_ID));
304+
check(!ret);
301305

302306
for (i = 0; i < N; i++) {
303307
strbuf_init(&recs[i].u.idx.last_key, 9);

0 commit comments

Comments
 (0)