[libvirt] [PATCHv2 02/15] api: add overflow error

Eric Blake eblake at redhat.com
Tue Mar 6 00:34:17 UTC 2012


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




More information about the libvir-list mailing list