]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
api: add overflow error
authorEric Blake <eblake@redhat.com>
Fri, 2 Mar 2012 23:58:05 +0000 (16:58 -0700)
committerEric Blake <eblake@redhat.com>
Thu, 8 Mar 2012 01:24:43 +0000 (18:24 -0700)
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.

daemon/remote.c
include/libvirt/virterror.h
src/libvirt.c
src/qemu/qemu_driver.c
src/util/virterror.c

index 39302cc3bd30d4abd336efdbd32e8b98c7ee09c0..0dd4f2e35410b43426d85dd53917d22c06d6db8e 100644 (file)
                          __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)
index a3f9199abdbef531f469e6a9d1abda183c2b2759..38ac15e05cc87c4fcf794c5c2c4755364ce31cd1 100644 (file)
@@ -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;
 
 /**
index 5de6e6800c6653470c0bd35de8a076bd402b9592..21b47660880ba04c91571f04b5283137fbb9cbbc 100644 (file)
@@ -8507,10 +8507,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) {
@@ -8774,11 +8778,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) &&
@@ -8853,11 +8861,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;
 
@@ -18618,11 +18630,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;
index ddb381a65556a3f35f28904fb87e3a50f4073148..b364b2c3c1e9dfd25c0ba713606f5cb126f37dd9 100644 (file)
@@ -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;
index 48c61a2e1280e6ba65e277a3a21e6e51da875e3f..b4e496ac77585c3a45b958d24321203205fa291f 100644 (file)
@@ -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);
 }