From 365911b182017f05122b88a574477ff945ae91ab Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 May 2024 14:05:58 -0400 Subject: [PATCH] qemu-io: add cvtnum() error handling for zone commands cvtnum() parses positive int64_t values and returns a negative errno on failure. Print errors and return early when cvtnum() fails. While we're at it, also reject nr_zones values greater or equal to 2^32 since they cannot be represented. Reported-by: Peter Maydell Cc: Sam Li Signed-off-by: Stefan Hajnoczi Message-ID: <20240507180558.377233-1-stefanha@redhat.com> Reviewed-by: Sam Li Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qemu-io-cmds.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index f5d7202a13..e2fab57183 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -1739,12 +1739,26 @@ static int zone_report_f(BlockBackend *blk, int argc, char **argv) { int ret; int64_t offset; + int64_t val; unsigned int nr_zones; ++optind; offset = cvtnum(argv[optind]); + if (offset < 0) { + print_cvtnum_err(offset, argv[optind]); + return offset; + } ++optind; - nr_zones = cvtnum(argv[optind]); + val = cvtnum(argv[optind]); + if (val < 0) { + print_cvtnum_err(val, argv[optind]); + return val; + } + if (val > UINT_MAX) { + printf("Number of zones must be less than 2^32\n"); + return -ERANGE; + } + nr_zones = val; g_autofree BlockZoneDescriptor *zones = NULL; zones = g_new(BlockZoneDescriptor, nr_zones); @@ -1780,8 +1794,16 @@ static int zone_open_f(BlockBackend *blk, int argc, char **argv) int64_t offset, len; ++optind; offset = cvtnum(argv[optind]); + if (offset < 0) { + print_cvtnum_err(offset, argv[optind]); + return offset; + } ++optind; len = cvtnum(argv[optind]); + if (len < 0) { + print_cvtnum_err(len, argv[optind]); + return len; + } ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len); if (ret < 0) { printf("zone open failed: %s\n", strerror(-ret)); @@ -1805,8 +1827,16 @@ static int zone_close_f(BlockBackend *blk, int argc, char **argv) int64_t offset, len; ++optind; offset = cvtnum(argv[optind]); + if (offset < 0) { + print_cvtnum_err(offset, argv[optind]); + return offset; + } ++optind; len = cvtnum(argv[optind]); + if (len < 0) { + print_cvtnum_err(len, argv[optind]); + return len; + } ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len); if (ret < 0) { printf("zone close failed: %s\n", strerror(-ret)); @@ -1830,8 +1860,16 @@ static int zone_finish_f(BlockBackend *blk, int argc, char **argv) int64_t offset, len; ++optind; offset = cvtnum(argv[optind]); + if (offset < 0) { + print_cvtnum_err(offset, argv[optind]); + return offset; + } ++optind; len = cvtnum(argv[optind]); + if (len < 0) { + print_cvtnum_err(len, argv[optind]); + return len; + } ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len); if (ret < 0) { printf("zone finish failed: %s\n", strerror(-ret)); @@ -1855,8 +1893,16 @@ static int zone_reset_f(BlockBackend *blk, int argc, char **argv) int64_t offset, len; ++optind; offset = cvtnum(argv[optind]); + if (offset < 0) { + print_cvtnum_err(offset, argv[optind]); + return offset; + } ++optind; len = cvtnum(argv[optind]); + if (len < 0) { + print_cvtnum_err(len, argv[optind]); + return len; + } ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len); if (ret < 0) { printf("zone reset failed: %s\n", strerror(-ret));