Skip to content

Commit eef93fb

Browse files
committed
Merge branch 'ps/reftable-alloc-failures' into jch
The reftable library is now prepared to expect that the memory allocation function given to it may fail to allocate and to deal with such an error. * ps/reftable-alloc-failures: (22 commits) reftable: handle trivial allocation failures reftable/tree: handle allocation failures reftable/pq: handle allocation failures when adding entries reftable/block: handle allocation failures reftable/blocksource: handle allocation failures reftable/iter: handle allocation failures when creating indexed table iter reftable/stack: handle allocation failures in auto compaction reftable/stack: handle allocation failures in `stack_compact_range()` reftable/stack: handle allocation failures in `reftable_new_stack()` reftable/stack: handle allocation failures on reload reftable/reader: handle allocation failures in `reader_init_iter()` reftable/reader: handle allocation failures for unindexed reader reftable/merged: handle allocation failures in `merged_table_init_iter()` reftable/writer: handle allocation failures in `reftable_new_writer()` reftable/writer: handle allocation failures in `writer_index_hash()` reftable/record: handle allocation failures when decoding records reftable/record: handle allocation failures on copy reftable/basics: handle allocation failures in `parse_names()` reftable/basics: handle allocation failures in `reftable_calloc()` reftable: introduce `reftable_strdup()` ...
2 parents 2790732 + 82b153f commit eef93fb

38 files changed

+848
-388
lines changed

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2720,7 +2720,6 @@ REFTABLE_OBJS += reftable/error.o
27202720
REFTABLE_OBJS += reftable/block.o
27212721
REFTABLE_OBJS += reftable/blocksource.o
27222722
REFTABLE_OBJS += reftable/iter.o
2723-
REFTABLE_OBJS += reftable/publicbasics.o
27242723
REFTABLE_OBJS += reftable/merged.o
27252724
REFTABLE_OBJS += reftable/pq.o
27262725
REFTABLE_OBJS += reftable/reader.o

refs/reftable-backend.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
13111311
struct reftable_log_record log = {0};
13121312
struct reftable_iterator it = {0};
13131313

1314-
reftable_stack_init_log_iterator(arg->stack, &it);
1314+
ret = reftable_stack_init_log_iterator(arg->stack, &it);
1315+
if (ret < 0)
1316+
goto done;
13151317

13161318
/*
13171319
* When deleting refs we also delete all reflog entries
@@ -1681,7 +1683,10 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
16811683
* copy over all log entries from the old reflog. Last but not least,
16821684
* when renaming we also have to delete all the old reflog entries.
16831685
*/
1684-
reftable_stack_init_log_iterator(arg->stack, &it);
1686+
ret = reftable_stack_init_log_iterator(arg->stack, &it);
1687+
if (ret < 0)
1688+
goto done;
1689+
16851690
ret = reftable_iterator_seek_log(&it, arg->oldname);
16861691
if (ret < 0)
16871692
goto done;
@@ -1902,7 +1907,10 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
19021907
if (ret < 0)
19031908
goto done;
19041909

1905-
reftable_stack_init_log_iterator(stack, &iter->iter);
1910+
ret = reftable_stack_init_log_iterator(stack, &iter->iter);
1911+
if (ret < 0)
1912+
goto done;
1913+
19061914
ret = reftable_iterator_seek_log(&iter->iter, "");
19071915
if (ret < 0)
19081916
goto done;
@@ -1969,7 +1977,10 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
19691977
if (refs->err < 0)
19701978
return refs->err;
19711979

1972-
reftable_stack_init_log_iterator(stack, &it);
1980+
ret = reftable_stack_init_log_iterator(stack, &it);
1981+
if (ret < 0)
1982+
goto done;
1983+
19731984
ret = reftable_iterator_seek_log(&it, refname);
19741985
while (!ret) {
19751986
ret = reftable_iterator_next_log(&it, &log);
@@ -1985,6 +1996,7 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
19851996
break;
19861997
}
19871998

1999+
done:
19882000
reftable_log_record_release(&log);
19892001
reftable_iterator_destroy(&it);
19902002
return ret;
@@ -2006,7 +2018,10 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
20062018
if (refs->err < 0)
20072019
return refs->err;
20082020

2009-
reftable_stack_init_log_iterator(stack, &it);
2021+
ret = reftable_stack_init_log_iterator(stack, &it);
2022+
if (ret < 0)
2023+
goto done;
2024+
20102025
ret = reftable_iterator_seek_log(&it, refname);
20112026
while (!ret) {
20122027
struct reftable_log_record log = {0};
@@ -2056,7 +2071,10 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
20562071
if (ret < 0)
20572072
goto done;
20582073

2059-
reftable_stack_init_log_iterator(stack, &it);
2074+
ret = reftable_stack_init_log_iterator(stack, &it);
2075+
if (ret < 0)
2076+
goto done;
2077+
20602078
ret = reftable_iterator_seek_log(&it, refname);
20612079
if (ret < 0)
20622080
goto done;
@@ -2162,7 +2180,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
21622180

21632181
reftable_writer_set_limits(writer, ts, ts);
21642182

2165-
reftable_stack_init_log_iterator(arg->stack, &it);
2183+
ret = reftable_stack_init_log_iterator(arg->stack, &it);
2184+
if (ret < 0)
2185+
goto out;
21662186

21672187
/*
21682188
* In order to delete a table we need to delete all reflog entries one
@@ -2186,6 +2206,7 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
21862206
ret = reftable_writer_add_log(writer, &tombstone);
21872207
}
21882208

2209+
out:
21892210
reftable_log_record_release(&log);
21902211
reftable_iterator_destroy(&it);
21912212
return ret;
@@ -2324,7 +2345,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
23242345
if (ret < 0)
23252346
goto done;
23262347

2327-
reftable_stack_init_log_iterator(stack, &it);
2348+
ret = reftable_stack_init_log_iterator(stack, &it);
2349+
if (ret < 0)
2350+
goto done;
23282351

23292352
ret = reftable_iterator_seek_log(&it, refname);
23302353
if (ret < 0)

reftable/basics.c

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,61 @@ license that can be found in the LICENSE file or at
77
*/
88

99
#include "basics.h"
10+
#include "reftable-basics.h"
11+
12+
static void *(*reftable_malloc_ptr)(size_t sz);
13+
static void *(*reftable_realloc_ptr)(void *, size_t);
14+
static void (*reftable_free_ptr)(void *);
15+
16+
void *reftable_malloc(size_t sz)
17+
{
18+
if (reftable_malloc_ptr)
19+
return (*reftable_malloc_ptr)(sz);
20+
return malloc(sz);
21+
}
22+
23+
void *reftable_realloc(void *p, size_t sz)
24+
{
25+
if (reftable_realloc_ptr)
26+
return (*reftable_realloc_ptr)(p, sz);
27+
return realloc(p, sz);
28+
}
29+
30+
void reftable_free(void *p)
31+
{
32+
if (reftable_free_ptr)
33+
reftable_free_ptr(p);
34+
else
35+
free(p);
36+
}
37+
38+
void *reftable_calloc(size_t nelem, size_t elsize)
39+
{
40+
size_t sz = st_mult(nelem, elsize);
41+
void *p = reftable_malloc(sz);
42+
if (!p)
43+
return NULL;
44+
memset(p, 0, sz);
45+
return p;
46+
}
47+
48+
char *reftable_strdup(const char *str)
49+
{
50+
size_t len = strlen(str);
51+
char *result = reftable_malloc(len + 1);
52+
if (!result)
53+
return NULL;
54+
memcpy(result, str, len + 1);
55+
return result;
56+
}
57+
58+
void reftable_set_alloc(void *(*malloc)(size_t),
59+
void *(*realloc)(void *, size_t), void (*free)(void *))
60+
{
61+
reftable_malloc_ptr = malloc;
62+
reftable_realloc_ptr = realloc;
63+
reftable_free_ptr = free;
64+
}
1065

1166
void put_be24(uint8_t *out, uint32_t i)
1267
{
@@ -75,14 +130,14 @@ size_t names_length(const char **names)
75130
return p - names;
76131
}
77132

78-
void parse_names(char *buf, int size, char ***namesp)
133+
char **parse_names(char *buf, int size)
79134
{
80135
char **names = NULL;
81136
size_t names_cap = 0;
82137
size_t names_len = 0;
83-
84138
char *p = buf;
85139
char *end = buf + size;
140+
86141
while (p < end) {
87142
char *next = strchr(p, '\n');
88143
if (next && next < end) {
@@ -92,14 +147,26 @@ void parse_names(char *buf, int size, char ***namesp)
92147
}
93148
if (p < next) {
94149
REFTABLE_ALLOC_GROW(names, names_len + 1, names_cap);
95-
names[names_len++] = xstrdup(p);
150+
if (!names)
151+
goto err;
152+
153+
names[names_len] = strdup(p);
154+
if (!names[names_len++])
155+
goto err;
96156
}
97157
p = next + 1;
98158
}
99159

100160
REFTABLE_REALLOC_ARRAY(names, names_len + 1);
101161
names[names_len] = NULL;
102-
*namesp = names;
162+
163+
return names;
164+
165+
err:
166+
for (size_t i = 0; i < names_len; i++)
167+
free(names[i]);
168+
free(names);
169+
return NULL;
103170
}
104171

105172
int names_equal(const char **a, const char **b)
@@ -121,3 +188,15 @@ int common_prefix_size(struct strbuf *a, struct strbuf *b)
121188

122189
return p;
123190
}
191+
192+
int hash_size(uint32_t id)
193+
{
194+
switch (id) {
195+
case 0:
196+
case GIT_SHA1_FORMAT_ID:
197+
return GIT_SHA1_RAWSZ;
198+
case GIT_SHA256_FORMAT_ID:
199+
return GIT_SHA256_RAWSZ;
200+
}
201+
abort();
202+
}

reftable/basics.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ license that can be found in the LICENSE file or at
1414
*/
1515

1616
#include "system.h"
17+
#include "reftable-basics.h"
1718

1819
/* Bigendian en/decoding of integers */
1920

@@ -37,9 +38,12 @@ size_t binsearch(size_t sz, int (*f)(size_t k, void *args), void *args);
3738
*/
3839
void free_names(char **a);
3940

40-
/* parse a newline separated list of names. `size` is the length of the buffer,
41-
* without terminating '\0'. Empty names are discarded. */
42-
void parse_names(char *buf, int size, char ***namesp);
41+
/*
42+
* Parse a newline separated list of names. `size` is the length of the buffer,
43+
* without terminating '\0'. Empty names are discarded. Returns a `NULL`
44+
* pointer when allocations fail.
45+
*/
46+
char **parse_names(char *buf, int size);
4347

4448
/* compares two NULL-terminated arrays of strings. */
4549
int names_equal(const char **a, const char **b);
@@ -53,6 +57,7 @@ void *reftable_malloc(size_t sz);
5357
void *reftable_realloc(void *p, size_t sz);
5458
void reftable_free(void *p);
5559
void *reftable_calloc(size_t nelem, size_t elsize);
60+
char *reftable_strdup(const char *str);
5661

5762
#define REFTABLE_ALLOC_ARRAY(x, alloc) (x) = reftable_malloc(st_mult(sizeof(*(x)), (alloc)))
5863
#define REFTABLE_CALLOC_ARRAY(x, alloc) (x) = reftable_calloc((alloc), sizeof(*(x)))
@@ -71,4 +76,6 @@ void *reftable_calloc(size_t nelem, size_t elsize);
7176
struct strbuf;
7277
int common_prefix_size(struct strbuf *a, struct strbuf *b);
7378

79+
int hash_size(uint32_t id);
80+
7481
#endif

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);

0 commit comments

Comments
 (0)