aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2014-07-17 11:41:53 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2014-07-18 13:12:15 +0100
commit12ac6d3db721a288c8953c5c253230aa0949a0e1 (patch)
treeab3f09b92659e40af1809e7f65030a56c3f29c68 /block/qcow2.c
parent5a7348045091a2bc15d85bb177e5956aa6114e5a (diff)
qcow2: Fix error path for unknown incompatible features
qcow2's report_unsupported_feature() had two bugs: A 32 bit truncation would prevent feature table entries for bits 32-63 from being used, and it could assign errp multiple times if there was more than one unknown feature, resulting in an error_set() assertion failure. Fix the truncation, make sure to set the error exactly once and add a qemu-iotests case for it. This fixes https://bugs.launchpad.net/qemu/+bug/1342704/ Reported-by: Maria Kustova <maria.k@catit.be> Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/qcow2.c')
-rw-r--r--block/qcow2.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/block/qcow2.c b/block/qcow2.c
index b0faa6917b..e1631d5086 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -210,20 +210,31 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
static void report_unsupported_feature(BlockDriverState *bs,
Error **errp, Qcow2Feature *table, uint64_t mask)
{
+ char *features = g_strdup("");
+ char *old;
+
while (table && table->name[0] != '\0') {
if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) {
- if (mask & (1 << table->bit)) {
- report_unsupported(bs, errp, "%.46s", table->name);
- mask &= ~(1 << table->bit);
+ if (mask & (1ULL << table->bit)) {
+ old = features;
+ features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "",
+ table->name);
+ g_free(old);
+ mask &= ~(1ULL << table->bit);
}
}
table++;
}
if (mask) {
- report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64,
- mask);
+ old = features;
+ features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64,
+ old, *old ? ", " : "", mask);
+ g_free(old);
}
+
+ report_unsupported(bs, errp, "%s", features);
+ g_free(features);
}
/*