Skip to content

Commit 0dd4458

Browse files
hanwengitster
authored andcommitted
reftable: signal overflow
reflog entries have unbounded size. In theory, each log ('g') block in reftable can have an arbitrary size, so the format allows for arbitrarily sized reflog messages. However, in the implementation, we are not scaling the log blocks up with the message, and writing a large message fails. This triggers a failure for reftable in t7006-pager.sh. Until this is fixed more structurally, report an error from within the reftable library for easier debugging. Signed-off-by: Han-Wen Nienhuys <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 019bd34 commit 0dd4458

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

reftable/error.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const char *reftable_error_str(int err)
3232
return "wrote empty table";
3333
case REFTABLE_REFNAME_ERROR:
3434
return "invalid refname";
35+
case REFTABLE_ENTRY_TOO_BIG_ERROR:
36+
return "entry too large";
3537
case -1:
3638
return "general error";
3739
default:

reftable/readwrite_test.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,40 @@ static void test_log_buffer_size(void)
155155
strbuf_release(&buf);
156156
}
157157

158+
static void test_log_overflow(void)
159+
{
160+
struct strbuf buf = STRBUF_INIT;
161+
char msg[256] = { 0 };
162+
struct reftable_write_options opts = {
163+
.block_size = ARRAY_SIZE(msg),
164+
};
165+
int err;
166+
struct reftable_log_record
167+
log = { .refname = "refs/heads/master",
168+
.update_index = 0xa,
169+
.value_type = REFTABLE_LOG_UPDATE,
170+
.value = { .update = {
171+
.name = "Han-Wen Nienhuys",
172+
.email = "[email protected]",
173+
.tz_offset = 100,
174+
.time = 0x5e430672,
175+
.message = msg,
176+
} } };
177+
struct reftable_writer *w =
178+
reftable_new_writer(&strbuf_add_void, &buf, &opts);
179+
180+
uint8_t hash1[GIT_SHA1_RAWSZ] = {1}, hash2[GIT_SHA1_RAWSZ] = { 2 };
181+
182+
memset(msg, 'x', sizeof(msg) - 1);
183+
log.value.update.old_hash = hash1;
184+
log.value.update.new_hash = hash2;
185+
reftable_writer_set_limits(w, update_index, update_index);
186+
err = reftable_writer_add_log(w, &log);
187+
EXPECT(err == REFTABLE_ENTRY_TOO_BIG_ERROR);
188+
reftable_writer_free(w);
189+
strbuf_release(&buf);
190+
}
191+
158192
static void test_log_write_read(void)
159193
{
160194
int N = 2;
@@ -648,5 +682,6 @@ int readwrite_test_main(int argc, const char *argv[])
648682
RUN_TEST(test_table_refs_for_no_index);
649683
RUN_TEST(test_table_refs_for_obj_index);
650684
RUN_TEST(test_write_empty_table);
685+
RUN_TEST(test_log_overflow);
651686
return 0;
652687
}

reftable/reftable-error.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ enum reftable_error {
5353

5454
/* Invalid ref name. */
5555
REFTABLE_REFNAME_ERROR = -10,
56+
57+
/* Entry does not fit. This can happen when writing outsize reflog
58+
messages. */
59+
REFTABLE_ENTRY_TOO_BIG_ERROR = -11,
5660
};
5761

5862
/* convert the numeric error code to a string. The string should not be

reftable/writer.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ static int writer_add_record(struct reftable_writer *w,
239239
writer_reinit_block_writer(w, reftable_record_type(rec));
240240
err = block_writer_add(w->block_writer, rec);
241241
if (err < 0) {
242+
/* we are writing into memory, so an error can only mean it
243+
* doesn't fit. */
244+
err = REFTABLE_ENTRY_TOO_BIG_ERROR;
242245
goto done;
243246
}
244247

0 commit comments

Comments
 (0)