Overflow can be user-induced, so it deserves more than being called an internal error. Note that in general, 32-bit platforms have far more places to trigger this error (anywhere the public API used 'unsigned long' but the other side of the connection is a 64-bit server); but some are possible on 64-bit platforms (where the public API computes the product of two numbers). * include/libvirt/virterror.h (VIR_ERR_OVERFLOW): New error. * src/util/virterror.c (virErrorMsg): Translate it. * src/libvirt.c (virDomainSetVcpusFlags, virDomainGetVcpuPinInfo) (virDomainGetVcpus, virDomainGetCPUStats): Use it. * daemon/remote.c (HYPER_TO_TYPE): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockResize): Likewise. --- v2: new daemon/remote.c | 17 +++++++++-------- include/libvirt/virterror.h | 3 ++- src/libvirt.c | 30 +++++++++++++++++++++++------- src/qemu/qemu_driver.c | 2 +- src/util/virterror.c | 6 ++++++ 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 74a5f16..be51d6f 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -57,14 +57,15 @@ __FUNCTION__, __LINE__, __VA_ARGS__) #if SIZEOF_LONG < 8 -# define HYPER_TO_TYPE(_type, _to, _from) \ - do { \ - if ((_from) != (_type)(_from)) { \ - virNetError(VIR_ERR_INTERNAL_ERROR, \ - _("conversion from hyper to %s overflowed"), #_type); \ - goto cleanup; \ - } \ - (_to) = (_from); \ +# define HYPER_TO_TYPE(_type, _to, _from) \ + do { \ + if ((_from) != (_type)(_from)) { \ + virNetError(VIR_ERR_OVERFLOW, \ + _("conversion from hyper to %s overflowed"), \ + #_type); \ + goto cleanup; \ + } \ + (_to) = (_from); \ } while (0) # define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index a3f9199..38ac15e 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -4,7 +4,7 @@ * Description: Provides the interfaces of the libvirt library to handle * errors raised while using the library. * - * Copy: Copyright (C) 2006, 2010-2011 Red Hat, Inc. + * Copy: Copyright (C) 2006, 2010-2012 Red Hat, Inc. * * See COPYING.LIB for the License of this software * @@ -246,6 +246,7 @@ typedef enum { VIR_ERR_AUTH_CANCELLED = 79, /* authentication cancelled */ VIR_ERR_NO_DOMAIN_METADATA = 80, /* The metadata is not present */ VIR_ERR_MIGRATE_UNSAFE = 81, /* Migration is not safe */ + VIR_ERR_OVERFLOW = 82, /* integer overflow */ } virErrorNumber; /** diff --git a/src/libvirt.c b/src/libvirt.c index 650252e..de23db8 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8506,10 +8506,14 @@ virDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, } /* Perform some argument validation common to all implementations. */ - if (nvcpus < 1 || (unsigned short) nvcpus != nvcpus) { + if (nvcpus < 1) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } + if ((unsigned short) nvcpus != nvcpus) { + virLibDomainError(VIR_ERR_OVERFLOW, _("input too large: %u"), nvcpus); + goto error; + } conn = domain->conn; if (conn->driver->domainSetVcpusFlags) { @@ -8773,11 +8777,15 @@ virDomainGetVcpuPinInfo(virDomainPtr domain, int ncpumaps, return -1; } - if (ncpumaps < 1 || !cpumaps || maplen <= 0 || - INT_MULTIPLY_OVERFLOW(ncpumaps, maplen)) { + if (ncpumaps < 1 || !cpumaps || maplen <= 0) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } + if (INT_MULTIPLY_OVERFLOW(ncpumaps, maplen)) { + virLibDomainError(VIR_ERR_OVERFLOW, _("input too large: %d * %d"), + ncpumaps, maplen); + goto error; + } /* At most one of these two flags should be set. */ if ((flags & VIR_DOMAIN_AFFECT_LIVE) && @@ -8852,11 +8860,15 @@ virDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo, /* Ensure that domainGetVcpus (aka remoteDomainGetVcpus) does not try to memcpy anything into a NULL pointer. */ - if (!cpumaps ? maplen != 0 - : (maplen <= 0 || INT_MULTIPLY_OVERFLOW(maxinfo, maplen))) { + if (!cpumaps ? maplen != 0 : maplen <= 0) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } + if (cpumaps && INT_MULTIPLY_OVERFLOW(maxinfo, maplen)) { + virLibDomainError(VIR_ERR_OVERFLOW, _("input too large: %d * %d"), + maxinfo, maplen); + goto error; + } conn = domain->conn; @@ -18613,11 +18625,15 @@ int virDomainGetCPUStats(virDomainPtr domain, if (start_cpu < -1 || (start_cpu == -1 && ncpus != 1) || ((params == NULL) != (nparams == 0)) || - (ncpus == 0 && params != NULL) || - (nparams && ncpus > UINT_MAX / nparams)) { + (ncpus == 0 && params != NULL)) { virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); goto error; } + if (nparams && ncpus > UINT_MAX / nparams) { + virLibDomainError(VIR_ERR_OVERFLOW, _("input too large: %u * %u"), + nparams, ncpus); + goto error; + } if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, VIR_DRV_FEATURE_TYPED_PARAM_STRING)) flags |= VIR_TYPED_PARAM_STRING_OKAY; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 733df0a..1bdd2f0 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7371,7 +7371,7 @@ qemuDomainBlockResize(virDomainPtr dom, /* We prefer operating on bytes. */ if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) { if (size > ULLONG_MAX / 1024) { - qemuReportError(VIR_ERR_INVALID_ARG, + qemuReportError(VIR_ERR_OVERFLOW, _("size must be less than %llu"), ULLONG_MAX / 1024); return -1; diff --git a/src/util/virterror.c b/src/util/virterror.c index 48c61a2..b4e496a 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1238,6 +1238,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Unsafe migration: %s"); break; + case VIR_ERR_OVERFLOW: + if (!info) + errmsg = _("numerical overflow"); + else + errmsg = _("numerical overflow: %s"); + break; } return (errmsg); } -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list