@@ -4309,7 +4309,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
QemuOptsList *create_opts = NULL;
QemuOpts *opts = NULL;
const char *backing_fmt, *backing_file;
- int64_t size;
+ uint64_t size;
+ int64_t backing_size;
BlockDriver *drv, *proto_drv;
Error *local_err = NULL;
int ret = 0;
@@ -4414,7 +4415,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
&local_err);
g_free(full_backing);
- if (!bs && size != -1) {
+ if (!bs && size != UINT64_MAX) {
/* Couldn't open BS, but we have a size, so it's nonfatal */
warn_reportf_err(local_err,
"Could not verify backing image. "
@@ -4426,22 +4427,24 @@ void bdrv_img_create(const char *filename, const char *fmt,
"Could not open backing image to determine size.\n");
goto out;
} else {
- if (size == -1) {
+ if (size == UINT64_MAX) {
/* Opened BS, have no size */
- size = bdrv_getlength(bs);
- if (size < 0) {
- error_setg_errno(errp, -size, "Could not get size of '%s'",
+ backing_size = bdrv_getlength(bs);
+ if (backing_size < 0) {
+ error_setg_errno(errp, -backing_size,
+ "Could not get size of '%s'",
backing_file);
bdrv_unref(bs);
goto out;
}
+ size = backing_size;
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, size, &error_abort);
}
bdrv_unref(bs);
}
} /* (backing_file && !(flags & BDRV_O_NO_BACKING)) */
- if (size == -1) {
+ if (size == UINT64_MAX) {
error_setg(errp, "Image creation needs a size parameter");
goto out;
}
@size is declared int64_t. It's set in two places. The second one assigns the (signed) value of bdrv_getlength(), then errors out if its negative. The first one assigns qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0), i.e. an uint64_t value. What if it exceeds INT64_MAX? Is that even possible? Turns out it is: $ qemu-img create -o size=9223372036854775808 foo.img On closer examination, the code still works as long as converting from uint64_t to int64_t and back doesn't change the value. Implementation-defined behavior, but sane implementations behave. Things actually break elsewhere for such sizes, e.g. file-posix.c's raw_create(). Clean this up. Signed-off-by: Markus Armbruster <armbru@redhat.com> --- block.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)