From 068db0239a84597147a62d02cfef5bcf840dbb4c Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 23 Jun 2010 10:48:10 -0300
Subject: [PATCH 05/11] qcow2: Fix qemu-img check segfault on corrupted images

RH-Author: Kevin Wolf <kwolf@redhat.com>
Message-id: <1277290092-8810-2-git-send-email-kwolf@redhat.com>
Patchwork-id: 10105
O-Subject: [RHEL-6 qemu-kvm PATCH 1/3] qcow2: Fix qemu-img check segfault on
	corrupted images
Bugzilla: 604210
RH-Acked-by: Amit Shah <amit.shah@redhat.com>
RH-Acked-by: Christoph Hellwig <chellwig@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>

Bugzilla: 604210

With corrupted images, we can easily get an cluster index that exceeds the
array size of the temporary refcount table.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6882c8fa78dcc4882640d3e11232d995fda7d5c4)
---
 block/qcow2-refcount.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 block/qcow2-refcount.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4355ceb..4781d53 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1141,22 +1141,30 @@ int qcow2_check_refcounts(BlockDriverState *bs)
                   s->refcount_table_offset,
                   s->refcount_table_size * sizeof(uint64_t));
     for(i = 0; i < s->refcount_table_size; i++) {
-        int64_t offset;
+        uint64_t offset, cluster;
         offset = s->refcount_table[i];
+        cluster = offset >> s->cluster_bits;
 
         /* Refcount blocks are cluster aligned */
         if (offset & (s->cluster_size - 1)) {
             fprintf(stderr, "ERROR refcount block %d is not "
                 "cluster aligned; refcount table entry corrupted\n", i);
             errors++;
+            continue;
+        }
+
+        if (cluster >= nb_clusters) {
+            fprintf(stderr, "ERROR refcount block %d is outside image\n", i);
+            errors++;
+            continue;
         }
 
         if (offset != 0) {
             errors += inc_refcounts(bs, refcount_table, nb_clusters,
                           offset, s->cluster_size);
-            if (refcount_table[offset / s->cluster_size] != 1) {
+            if (refcount_table[cluster] != 1) {
                 fprintf(stderr, "ERROR refcount block %d refcount=%d\n",
-                    i, refcount_table[offset / s->cluster_size]);
+                    i, refcount_table[cluster]);
             }
         }
     }
-- 
1.7.0.3

