aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2-snapshot.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2019-10-11 17:28:09 +0200
committerMax Reitz <mreitz@redhat.com>2019-10-28 11:54:02 +0100
commit624143355cb6e4149ec27b9b00088aeb958da31d (patch)
treeebbe0e6b85ab005b1065d0e853de0fdeeada2901 /block/qcow2-snapshot.c
parentf91f1f159bcaa81a70e860079a73ae7d1220dc0c (diff)
downloadqemu-624143355cb6e4149ec27b9b00088aeb958da31d.zip
qemu-624143355cb6e4149ec27b9b00088aeb958da31d.tar.gz
qemu-624143355cb6e4149ec27b9b00088aeb958da31d.tar.bz2
qcow2: Keep track of the snapshot table length
When repairing the snapshot table, we truncate entries that have too much extra data. This frees up space that we do not have to count towards the snapshot table size. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20191011152814.14791-12-mreitz@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'block/qcow2-snapshot.c')
-rw-r--r--block/qcow2-snapshot.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 53dc163..582eb33 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -68,6 +68,7 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
QCowSnapshot *sn;
int i, id_str_size, name_size;
int64_t offset;
+ uint64_t table_length = 0;
int ret;
if (!s->nb_snapshots) {
@@ -82,6 +83,8 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
for(i = 0; i < s->nb_snapshots; i++) {
bool truncate_unknown_extra_data = false;
+ table_length = ROUND_UP(table_length, 8);
+
/* Read statically sized part of the snapshot header */
offset = ROUND_UP(offset, 8);
ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
@@ -184,7 +187,16 @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
offset += name_size;
sn->name[name_size] = '\0';
- if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
+ /* Note that the extra data may have been truncated */
+ table_length += sizeof(h) + sn->extra_data_size + id_str_size +
+ name_size;
+ if (!repair) {
+ assert(table_length == offset - s->snapshots_offset);
+ }
+
+ if (table_length > QCOW_MAX_SNAPSHOTS_SIZE ||
+ offset - s->snapshots_offset > INT_MAX)
+ {
ret = -EFBIG;
error_setg(errp, "Snapshot table is too big");
goto fail;