If the qcow2 check function detects a refcount block located beyond the
image end, grow the image appropriately. This cannot break anything and
is the logical fix for such a case.
Signed-off-by: Max Reitz <address@hidden>
---
block/qcow2-refcount.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 59 insertions(+), 4 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index d484029..3800d3c 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1544,7 +1544,8 @@ static int check_refblocks(BlockDriverState *bs,
BdrvCheckResult *res,
int64_t *nb_clusters)
{
BDRVQcowState *s = bs->opaque;
- int64_t i;
+ int64_t i, size;
+ int ret;
for(i = 0; i < s->refcount_table_size; i++) {
uint64_t offset, cluster;
@@ -1560,9 +1561,63 @@ static int check_refblocks(BlockDriverState *bs,
BdrvCheckResult *res,
}
if (cluster >= *nb_clusters) {
- fprintf(stderr, "ERROR refcount block %" PRId64
- " is outside image\n", i);
- res->corruptions++;
+ fprintf(stderr, "%s refcount block %" PRId64 " is outside image\n",
+ fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
+
+ if (fix & BDRV_FIX_ERRORS) {
+ int64_t old_nb_clusters = *nb_clusters;
+
+ if (offset + s->cluster_size < offset ||
+ offset > INT64_MAX - s->cluster_size)