aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/qcow2-refcount.c19
-rwxr-xr-xtests/qemu-iotests/13812
-rw-r--r--tests/qemu-iotests/138.out5
3 files changed, 28 insertions, 8 deletions
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index ed3d8ebd57..21e50dacf4 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1520,12 +1520,31 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
{
BDRVQcow2State *s = bs->opaque;
uint64_t start, last, cluster_offset, k, refcount;
+ int64_t file_len;
int ret;
if (size <= 0) {
return 0;
}
+ file_len = bdrv_getlength(bs->file->bs);
+ if (file_len < 0) {
+ return file_len;
+ }
+
+ /*
+ * Last cluster of qcow2 image may be semi-allocated, so it may be OK to
+ * reference some space after file end but it should be less than one
+ * cluster.
+ */
+ if (offset + size - file_len >= s->cluster_size) {
+ fprintf(stderr, "ERROR: counting reference for region exceeding the "
+ "end of the file by one cluster or more: offset 0x%" PRIx64
+ " size 0x%" PRIx64 "\n", offset, size);
+ res->corruptions++;
+ return 0;
+ }
+
start = start_of_cluster(s, offset);
last = start_of_cluster(s, offset + size - 1);
for(cluster_offset = start; cluster_offset <= last;
diff --git a/tests/qemu-iotests/138 b/tests/qemu-iotests/138
index f353ac8219..6a731370db 100755
--- a/tests/qemu-iotests/138
+++ b/tests/qemu-iotests/138
@@ -54,15 +54,13 @@ $QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
# Put the data cluster at a multiple of 2 TB, resulting in the image apparently
# having a multiple of 2^32 clusters
# (To be more specific: It is at 32 PB)
-poke_file "$TEST_IMG" 2048 "\x80\x80\x00\x00\x00\x00\x00\x00"
+poke_file "$TEST_IMG" $((2048 + 8)) "\x00\x80\x00\x00\x00\x00\x00\x00"
# An offset of 32 PB results in qemu-img check having to allocate an in-memory
-# refcount table of 128 TB (16 bit refcounts, 512 byte clusters).
-# This should be generally too much for any system and thus fail.
-# What this test is checking is that the qcow2 driver actually tries to allocate
-# such a large amount of memory (and is consequently aborting) instead of having
-# truncated the cluster count somewhere (which would result in much less memory
-# being allocated and then a segfault occurring).
+# refcount table of 128 TB (16 bit refcounts, 512 byte clusters), if qemu-img
+# don't check that referenced data cluster is far beyond the end of file.
+# But starting from 4.0, qemu-img does this check, and instead of "Cannot
+# allocate memory", we have an error showing that l2 entry is invalid.
_check_test_img
# success, all done
diff --git a/tests/qemu-iotests/138.out b/tests/qemu-iotests/138.out
index 3fe911f85a..aca7d47a80 100644
--- a/tests/qemu-iotests/138.out
+++ b/tests/qemu-iotests/138.out
@@ -5,5 +5,8 @@ QA output created by 138
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=512
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Check failed: Cannot allocate memory
+ERROR: counting reference for region exceeding the end of the file by one cluster or more: offset 0x80000000000000 size 0x200
+
+1 errors were found on the image.
+Data may be corrupted, or further writes to the image may corrupt it.
*** done