]> git.ipfire.org Git - thirdparty/git.git/commitdiff
refs/reftable: fix uninitialized memory access of `max_index`
authorKarthik Nayak <karthik.188@gmail.com>
Mon, 27 Jan 2025 09:44:08 +0000 (10:44 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Jan 2025 16:21:41 +0000 (08:21 -0800)
When migrating reflogs between reference backends, maintaining the
original order of the reflog entries is crucial. To achieve this, an
`index` field is stored within the `ref_update` struct that encodes the
relative order of reflog entries. This field is used by the reftable
backend as update index for the respective reflog entries to maintain
that ordering.

These update indices must be respected when writing table headers, which
encode the minimum and maximum update index of contained records in the
header and footer. This logic was added in commit bc67b4ab5f (reftable:
write correct max_update_index to header, 2025-01-15), which started to
use `reftable_writer_set_limits()` to propagate the mininum and maximum
update index of all records contained in a ref transaction.

However, we only set the maximum update index for the first transaction
argument, even though there can be multiple such arguments. This is the
case when we write to multiple stacks in a single transaction, e.g. when
updating references in two different worktrees at once. Consequently,
the update index for all but the first argument remain uninitialized,
which may cause undefined behaviour.

Fix this by moving the assignment of the maximum update index in
`reftable_be_transaction_finish()` inside the loop, which ensures that
all elements of the array are correctly initialized.

Furthermore, initialize the `max_index` field to 0 when queueing a new
transaction argument. This is not strictly necessary, as all elements of
`write_transaction_table_arg.max_index` are now assigned correctly.
However, this initialization is added for consistency and to safeguard
against potential future changes that might inadvertently introduce
uninitialized memory access.

Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs/reftable-backend.c

index 68db2baa8f15c44453656661f5295dbc0596b563..bb658826fe60a73707896e374268bd45c3b17cce 100644 (file)
@@ -920,6 +920,7 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
                arg->updates_nr = 0;
                arg->updates_alloc = 0;
                arg->updates_expected = 0;
+               arg->max_index = 0;
        }
 
        arg->updates_expected++;
@@ -1502,10 +1503,9 @@ static int reftable_be_transaction_finish(struct ref_store *ref_store UNUSED,
        struct reftable_transaction_data *tx_data = transaction->backend_data;
        int ret = 0;
 
-       if (tx_data->args)
-               tx_data->args->max_index = transaction->max_index;
-
        for (size_t i = 0; i < tx_data->args_nr; i++) {
+               tx_data->args[i].max_index = transaction->max_index;
+
                ret = reftable_addition_add(tx_data->args[i].addition,
                                            write_transaction_table, &tx_data->args[i]);
                if (ret < 0)