]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce virStrncpy.
authorChris Lalancette <clalance@redhat.com>
Mon, 3 Aug 2009 12:37:44 +0000 (14:37 +0200)
committerChris Lalancette <clalance@redhat.com>
Tue, 22 Sep 2009 18:10:00 +0000 (20:10 +0200)
Add the virStrncpy function, which takes a dst string, source string,
the number of bytes to copy and the number of bytes available in the
dest string.  If the source string is too large to fit into the
destination string, including the \0 byte, then no data is copied and
the function returns NULL.  Otherwise, this function copies n bytes
from source into dst, including the \0, and returns a pointer to the
dst string.  This function is intended to replace all unsafe uses
of strncpy in the code base, since strncpy does *not* guarantee that
the buffer terminates with a \0.

Signed-off-by: Chris Lalancette <clalance@redhat.com>
27 files changed:
HACKING
cfg.mk
daemon/Makefile.am
daemon/libvirtd.c
daemon/remote.c
proxy/libvirt_proxy.c
src/datatypes.c
src/esx/esx_driver.c
src/esx/esx_vmx.c
src/lxc/lxc_controller.c
src/lxc/lxc_driver.c
src/nodeinfo.c
src/opennebula/one_client.c
src/openvz/openvz_conf.c
src/phyp/phyp_driver.c
src/qemu/qemu_conf.c
src/qemu/qemu_driver.c
src/remote/remote_driver.c
src/test/test_driver.c
src/uml/uml_driver.c
src/util/bridge.c
src/util/util.c
src/util/util.h
src/xen/proxy_internal.c
src/xen/xen_hypervisor.c
src/xen/xend_internal.c
src/xen/xm_internal.c

diff --git a/HACKING b/HACKING
index da28e98bf0af86343a4c8d207377747f84ab5200..bcff8c63312a707ae566afcbfbf542091044d63a 100644 (file)
--- a/HACKING
+++ b/HACKING
@@ -231,6 +231,37 @@ one of the following semantically named macros
 
 
 
+String copying
+==============
+
+Do not use the strncpy function.  According to the man page, it does
+*not* guarantee a NULL-terminated buffer, which makes it extremely dangerous
+to use.  Instead, use one of the functionally equivalent functions:
+
+  - virStrncpy(char *dest, const char *src, size_t n, size_t destbytes)
+      The first three arguments have the same meaning as for strncpy; namely the
+      destination, source, and number of bytes to copy, respectively.  The last
+      argument is the number of bytes available in the destination string; if a
+      copy of the source string (including a \0) will not fit into the
+      destination, no bytes are copied and the routine returns NULL.
+      Otherwise, n bytes from the source are copied into the destination and a
+      trailing \0 is appended.
+
+  - virStrcpy(char *dest, const char *src, size_t destbytes)
+      Use this variant if you know you want to copy the entire src string
+      into dest.  Note that this is a macro, so arguments could be
+      evaluated more than once.  This is equivalent to
+      virStrncpy(dest, src, strlen(src), destbytes)
+
+  - virStrcpyStatic(char *dest, const char *src)
+      Use this variant if you know you want to copy the entire src string
+      into dest *and* you know that your destination string is a static string
+      (i.e. that sizeof(dest) returns something meaningful).  Note that
+      this is a macro, so arguments could be evaluated more than once.  This is
+      equivalent to virStrncpy(dest, src, strlen(src), sizeof(dest)).
+
+
+
 Variable length string buffer
 =============================
 
diff --git a/cfg.mk b/cfg.mk
index 64bd26e0ffbdd5b43894918d02899cbb0dabc9ee..2d2dd7ec8ea1ef79d6f226429c723432043cad0a 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -91,6 +91,12 @@ sc_prohibit_asprintf:
        msg='use virAsprintf, not a'sprintf                             \
          $(_prohibit_regexp)
 
+sc_prohibit_strncpy:
+       @grep -nE 'strncpy *\('                                         \
+           $$($(VC_LIST) | grep -v 'src/util.c') &&                    \
+         { echo '$(ME): use virStrncpy, not strncpy'                   \
+               1>&2; exit 1; } || :
+
 sc_prohibit_VIR_ERR_NO_MEMORY:
        @re='\<V''IR_ERR_NO_MEMORY\>'                                   \
        msg='use virReportOOMError, not V'IR_ERR_NO_MEMORY              \
index 61822ec9f5e113ec7c785255cb5b8df8ad74cb2e..8d9f00f66a0c9614bc7e712e832764525d5970f8 100644 (file)
@@ -73,9 +73,10 @@ libvirtd_LDADD =                                     \
        $(SASL_LIBS)                                    \
        $(POLKIT_LIBS)
 
+libvirtd_LDADD += ../src/libvirt_util.la
+
 if WITH_DRIVER_MODULES
   libvirtd_LDADD += ../src/libvirt_driver.la
-  libvirtd_LDADD += ../src/libvirt_util.la
 else
 if WITH_QEMU
     libvirtd_LDADD += ../src/libvirt_driver_qemu.la
index 07960e195709d9f4a8eaf25e75ca4ebc74aeea3b..2bae782e7c2263e98315000e803eae1f6013cdd2 100644 (file)
@@ -507,11 +507,13 @@ static int qemudListenUnix(struct qemud_server *server,
 
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
+    if (virStrcpyStatic(addr.sun_path, path) == NULL) {
+        VIR_ERROR(_("Path %s too long for unix socket"), path);
+        goto cleanup;
+    }
     if (addr.sun_path[0] == '@')
         addr.sun_path[0] = '\0';
 
-
     oldgrp = getgid();
     oldmask = umask(readonly ? ~unix_sock_ro_mask : ~unix_sock_rw_mask);
     if (server->privileged)
index 17426cd0840981781dbda6964af1ab8b7abbf6f7..6d4cc1c311ca716ef4af7316acc66cd47fb53f06 100644 (file)
@@ -556,9 +556,11 @@ remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUT
 
     /* Deserialise parameters. */
     for (i = 0; i < nparams; ++i) {
-        strncpy (params[i].field, args->params.params_val[i].field,
-                 VIR_DOMAIN_SCHED_FIELD_LENGTH);
-        params[i].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+        if (virStrcpyStatic(params[i].field, args->params.params_val[i].field) == NULL) {
+            remoteDispatchFormatError(rerr, _("Field %s too big for destination"),
+                                      args->params.params_val[i].field);
+            return -1;
+        }
         params[i].type = args->params.params_val[i].value.type;
         switch (params[i].type) {
         case VIR_DOMAIN_SCHED_FIELD_INT:
index aa20d2850feae9176f5cc6b6ba8a308518756359..e5298fd4be5e8ea2c031e9d069f4c1eab689f931 100644 (file)
@@ -170,7 +170,11 @@ proxyListenUnixSocket(const char *path) {
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
     addr.sun_path[0] = '\0';
-    strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
+    if (virStrcpy(&addr.sun_path[1], path, sizeof(addr.sun_path) - 1) == NULL) {
+        fprintf(stderr, "Path %s too long to fit into destination\n", path);
+        close(fd);
+        return -1;
+    }
 
     /*
      * now bind the socket to that address and listen on it
index d7cf2ee51685e27425aa8e7087e5504a0567f540..530076c0ba804d2bd9d74a5372bd29ea1f62c595 100644 (file)
@@ -26,6 +26,7 @@
 #include "logging.h"
 #include "memory.h"
 #include "uuid.h"
+#include "util.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -926,8 +927,12 @@ virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const c
             virReportOOMError(conn);
             goto error;
         }
-        strncpy(ret->key, key, sizeof(ret->key)-1);
-        ret->key[sizeof(ret->key)-1] = '\0';
+        if (virStrcpyStatic(ret->key, key) == NULL) {
+            virMutexUnlock(&conn->lock);
+            virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
+                            _("Volume key %s too large for destination"), key);
+            goto error;
+        }
         ret->magic = VIR_STORAGE_VOL_MAGIC;
         ret->conn = conn;
 
index 8fad457fd3f8def1a2c561f0ea6a7b2c1d29aecf..1ef894f42ad53a032d0b03f3e560ade14ca90ac1 100644 (file)
@@ -755,9 +755,14 @@ esxNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
                 ++ptr;
             }
 
-            strncpy (nodeinfo->model, dynamicProperty->val->string,
-                     sizeof (nodeinfo->model) - 1);
-            nodeinfo->model[sizeof (nodeinfo->model) - 1] = '\0';
+            if (virStrncpy(nodeinfo->model, dynamicProperty->val->string,
+                           sizeof(nodeinfo->model) - 1,
+                           sizeof(nodeinfo->model)) == NULL) {
+                ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
+                          "CPU Model %s too long for destination",
+                          dynamicProperty->val->string);
+                goto failure;
+            }
         } else {
             VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
         }
index 6bd6b93880d80d115982f1824879755b484231da..9a0191ead7d33a37e145e9e0d7bbe070b2280f7d 100644 (file)
@@ -877,35 +877,21 @@ failure:
 char *
 esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix)
 {
-    char buffer[32] = "";
     char *name = NULL;
-    size_t length = strlen(prefix);
 
-    if (length > sizeof (buffer) - 2 - 1) {
+    if (idx < 0) {
         ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
-                  "Disk name prefix '%s' is too long", prefix);
-        return NULL;
-    }
-
-    strncpy(buffer, prefix, sizeof (buffer) - 1);
-    buffer[sizeof (buffer) - 1] = '\0';
-
-    if (idx < 26) {
-        buffer[length] = 'a' + idx;
+                  "Disk index %d is negative", idx);
+    } else if (idx < 26) {
+        if (virAsprintf(&name, "%s%c", prefix, 'a' + idx) < 0)
+            virReportOOMError(conn);
     } else if (idx < 702) {
-        buffer[length] = 'a' + idx / 26 - 1;
-        buffer[length + 1] = 'a' + idx % 26;
+        if (virAsprintf(&name, "%s%c%c", prefix, 'a' + idx / 26 - 1,
+                        'a' + (idx % 26)) < 0)
+            virReportOOMError(conn);
     } else {
         ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
                   "Disk index %d is too large", idx);
-        return NULL;
-    }
-
-    name = strdup(buffer);
-
-    if (name == NULL) {
-        virReportOOMError(conn);
-        return NULL;
     }
 
     return name;
index a0db602a8cdde5e323eb7159e199f2a10dd5a211..bca721b3ce8f541bbac0caf25e9123c3cc2f7c28 100644 (file)
@@ -178,7 +178,11 @@ static int lxcMonitorServer(const char *sockpath)
     unlink(sockpath);
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
+    if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) {
+        lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                 _("Socket path %s too long for destination"), sockpath);
+        goto error;
+    }
 
     if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
         virReportSystemError(NULL, errno,
index 1fd6cdd7ec721579959990c7c8293a0a8984b859..0a9cc285ec114e7ac2e2cfcb5ad016f7e9e81856 100644 (file)
@@ -719,7 +719,11 @@ static int lxcMonitorClient(virConnectPtr conn,
 
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, sockpath, sizeof(addr.sun_path));
+    if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) {
+        lxcError(conn, NULL, VIR_ERR_INTERNAL_ERROR,
+                 _("Socket path %s too big for destination"), sockpath);
+        goto error;
+    }
 
     if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
         virReportSystemError(conn, errno, "%s",
@@ -1738,7 +1742,11 @@ static int lxcGetSchedulerParameters(virDomainPtr domain,
     if (virCgroupGetCpuShares(group, &val) != 0)
         goto cleanup;
     params[0].value.ul = val;
-    strncpy(params[0].field, "cpu_shares", sizeof(params[0].field));
+    if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
+        lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR,
+                 "%s", _("Field cpu_shares too big for destination"));
+        goto cleanup;
+    }
     params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
 
     ret = 0;
index 0a211a7acceb0c464ce98e6cc20dcd00c2b51aae..7d26b2be029a007effc1a3bbaeb1bdea2398b709 100644 (file)
@@ -141,8 +141,8 @@ int nodeGetInfo(virConnectPtr conn,
 
     uname(&info);
 
-    strncpy(nodeinfo->model, info.machine, sizeof(nodeinfo->model)-1);
-    nodeinfo->model[sizeof(nodeinfo->model)-1] = '\0';
+    if (virStrcpyStatic(nodeinfo->model, info.machine) == NULL)
+        return -1;
 
 #else /* !HAVE_UNAME */
 
index 21f303a64bae87d1f83269e88c166cee8d18e712..39bb1ea69fb0a193f24642022def3da8aae27bb5 100644 (file)
@@ -24,6 +24,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include "one_client.h"
+#include "datatypes.h"
+#include "util.h"
 
 oneClient one_client;
 
@@ -171,7 +173,7 @@ int c_oneFinalize(int vmid)
     return c_oneAction(vmid, (char *)"finalize");
 }
 
-int c_oneVmInfo(int vmid, char* ret_info,int length)
+int c_oneVmInfo(int vmid, char* ret_info, int length)
 {
     xmlrpc_value *resultP;
     int return_code;
@@ -186,10 +188,9 @@ int c_oneVmInfo(int vmid, char* ret_info,int length)
 
     if( return_code )
     {
-        strncpy(ret_info, return_string, length-1);
-        ret_info[length-1] = '\0';
-
-        retval = 0;
+        if (virStrncpy(ret_info, return_string, length-1, length) != NULL)
+            /* Only set the return value to 0 if we succeeded */
+            retval = 0;
     }
 
     xmlrpc_DECREF(resultP);
index be94b9eff310635efcad629f26121c7bb267fb4c..403f537533cbaa17d49331750ec846a5628e2d99 100644 (file)
@@ -260,8 +260,11 @@ openvzReadNetworkConf(virConnectPtr conn,
                     if (VIR_ALLOC_N(net->ifname, len+1) < 0)
                         goto no_memory;
 
-                    strncpy(net->ifname, p, len);
-                    net->ifname[len] = '\0';
+                    if (virStrncpy(net->ifname, p, len, len+1) == NULL) {
+                        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                                    _("Network ifname %s too long for destination"), p);
+                        goto error;
+                    }
                 } else if (STRPREFIX(p, "bridge=")) {
                     p += 7;
                     len = next - p;
@@ -274,8 +277,11 @@ openvzReadNetworkConf(virConnectPtr conn,
                     if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0)
                         goto no_memory;
 
-                    strncpy(net->data.bridge.brname, p, len);
-                    net->data.bridge.brname[len] = '\0';
+                    if (virStrncpy(net->data.bridge.brname, p, len, len+1) == NULL) {
+                        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                                    _("Bridge name %s too long for destination"), p);
+                        goto error;
+                    }
                 } else if (STRPREFIX(p, "mac=")) {
                     p += 4;
                     len = next - p;
@@ -284,8 +290,11 @@ openvzReadNetworkConf(virConnectPtr conn,
                               "%s", _("Wrong length MAC address"));
                         goto error;
                     }
-                    strncpy(cpy_temp, p, len);
-                    cpy_temp[len] = '\0';
+                    if (virStrncpy(cpy_temp, p, len, sizeof(cpy_temp)) == NULL) {
+                        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+                                    _("MAC address %s too long for destination"), p);
+                        goto error;
+                    }
                     if (virParseMacAddr(cpy_temp, net->mac) < 0) {
                         openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("Wrong MAC address"));
@@ -628,8 +637,10 @@ openvzReadConfigParam(const char * conf_file ,const char * param, char *value, i
             if (sf[0] == '=' && sf[1] != '\0' ) {
                 sf ++;
                 if ((token = strtok_r(sf,"\"\t\n", &saveptr)) != NULL) {
-                    strncpy(value, token, maxlen) ;
-                    value[maxlen-1] = '\0';
+                    if (virStrcpy(value, token, maxlen) == NULL) {
+                        ret = -1;
+                        break;
+                    }
                     found = 1;
                 }
             }
@@ -810,6 +821,7 @@ openvzGetVPSUUID(int vpsid, char *uuidstr, size_t len)
     char uuidbuf[1024];
     char iden[1024];
     int fd, ret;
+    int retval = 0;
 
     if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
        return -1;
@@ -832,13 +844,14 @@ openvzGetVPSUUID(int vpsid, char *uuidstr, size_t len)
 
         sscanf(line, "%s %s\n", iden, uuidbuf);
         if(STREQ(iden, "#UUID:")) {
-            strncpy(uuidstr, uuidbuf, len);
+            if (virStrcpy(uuidstr, uuidbuf, len) == NULL)
+                retval = -1;
             break;
         }
     }
     close(fd);
 
-    return 0;
+    return retval;
 }
 
 /* Do actual checking for UUID presence in conf file,
index e2a2caf2c1cf9b6716f1caaf7c711fa91d00b838..fbb8982ed8033190a569a7057ed21d422c032d29 100644 (file)
@@ -1451,7 +1451,7 @@ escape_specialcharacters(char *src, char *dst, size_t dstlen)
     }
     temp_buffer[j] = '\0';
 
-    if (strncpy(dst, temp_buffer, dstlen) == NULL)
+    if (virStrcpy(dst, temp_buffer, dstlen) == NULL)
         return -1;
 
     return 0;
index 8f2774bb9b24b1a56e66a60ca88e632d3994bba0..309f17155b136f293ace18c485e90809e8017a04 100644 (file)
@@ -1393,18 +1393,18 @@ static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
 {
     switch (dev->type) {
     case VIR_DOMAIN_CHR_TYPE_NULL:
-        strncpy(buf, "null", buflen);
-        buf[buflen-1] = '\0';
+        if (virStrcpy(buf, "null", buflen) == NULL)
+            return -1;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_VC:
-        strncpy(buf, "vc", buflen);
-        buf[buflen-1] = '\0';
+        if (virStrcpy(buf, "vc", buflen) == NULL)
+            return -1;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_PTY:
-        strncpy(buf, "pty", buflen);
-        buf[buflen-1] = '\0';
+        if (virStrcpy(buf, "pty", buflen) == NULL)
+            return -1;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_DEV:
@@ -1426,8 +1426,8 @@ static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
         break;
 
     case VIR_DOMAIN_CHR_TYPE_STDIO:
-        strncpy(buf, "stdio", buflen);
-        buf[buflen-1] = '\0';
+        if (virStrcpy(buf, "stdio", buflen) == NULL)
+            return -1;
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UDP:
index 942aff20951546b5b5581d6bd4772357ad557d86..af215caee19ca7535f59d98f813a79d17c8c5852 100644 (file)
@@ -1010,7 +1010,11 @@ qemudOpenMonitorUnix(virConnectPtr conn,
 
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, monitor, sizeof(addr.sun_path));
+    if (virStrcpyStatic(addr.sun_path, monitor) == NULL) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         _("Monitor path %s too big for destination"), monitor);
+        goto error;
+    }
 
     do {
         ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
@@ -6559,8 +6563,12 @@ static int qemuGetSchedulerParameters(virDomainPtr dom,
         goto cleanup;
     }
     params[0].value.ul = val;
-    strncpy(params[0].field, "cpu_shares", sizeof(params[0].field));
     params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
+    if (virStrcpyStatic(params[0].field, "cpu_shares") == NULL) {
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("Field cpu_shares too long for destination"));
+        goto cleanup;
+    }
 
     ret = 0;
 
index 24bef73c49db9c6fdbfc74389eb49e0ec6e017a7..cf12bf5107697064e02f4371f101ef9b5da8817f 100644 (file)
@@ -654,7 +654,11 @@ doRemoteOpen (virConnectPtr conn,
 
         memset (&addr, 0, sizeof addr);
         addr.sun_family = AF_UNIX;
-        strncpy (addr.sun_path, sockname, UNIX_PATH_MAX (addr));
+        if (virStrcpyStatic(addr.sun_path, sockname) == NULL) {
+            errorf(conn, VIR_ERR_INTERNAL_ERROR,
+                   _("Socket %s too big for destination"), sockname);
+            goto failed;
+        }
         if (addr.sun_path[0] == '@')
             addr.sun_path[0] = '\0';
 
@@ -1569,8 +1573,8 @@ remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
               (xdrproc_t) xdr_remote_node_get_info_ret, (char *) &ret) == -1)
         goto done;
 
-    strncpy (info->model, ret.model, 32);
-    info->model[31] = '\0';
+    if (virStrcpyStatic(info->model, ret.model) == NULL)
+        goto done;
     info->memory = ret.memory;
     info->cpus = ret.cpus;
     info->mhz = ret.mhz;
@@ -3001,9 +3005,12 @@ remoteDomainGetSchedulerParameters (virDomainPtr domain,
 
     /* Deserialise the result. */
     for (i = 0; i < *nparams; ++i) {
-        strncpy (params[i].field, ret.params.params_val[i].field,
-                 VIR_DOMAIN_SCHED_FIELD_LENGTH);
-        params[i].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+        if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
+            errorf(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                   _("Parameter %s too big for destination"),
+                   ret.params.params_val[i].field);
+            goto cleanup;
+        }
         params[i].type = ret.params.params_val[i].value.type;
         switch (params[i].type) {
         case VIR_DOMAIN_SCHED_FIELD_INT:
index 10ec141f3463b5b653c1645e1c28e5077e08d116..cb48f648a8ab0b73f0c546c805573e17eb1c24d7 100644 (file)
@@ -412,10 +412,13 @@ static char *testBuildFilename(const char *relativeTo,
     offset = strrchr(relativeTo, '/');
     if ((baseLen = (offset-relativeTo+1))) {
         char *absFile;
-        if (VIR_ALLOC_N(absFile, baseLen + strlen(filename) + 1) < 0)
+        int totalLen = baseLen + strlen(filename) + 1;
+        if (VIR_ALLOC_N(absFile, totalLen) < 0)
             return NULL;
-        strncpy(absFile, relativeTo, baseLen);
-        absFile[baseLen] = '\0';
+        if (virStrncpy(absFile, relativeTo, baseLen, totalLen) == NULL) {
+            VIR_FREE(absFile);
+            return NULL;
+        }
         strcat(absFile, filename);
         return absFile;
     } else {
@@ -568,8 +571,11 @@ static int testOpenFromFile(virConnectPtr conn,
 
     privconn->nextDomID = 1;
     privconn->numCells = 0;
-    strncpy(privconn->path, file, PATH_MAX-1);
-    privconn->path[PATH_MAX-1] = '\0';
+    if (virStrcpyStatic(privconn->path, file) == NULL) {
+        testError(NULL, VIR_ERR_INTERNAL_ERROR,
+                  _("Path %s too big for destination"), file);
+        goto error;
+    }
     memmove(&privconn->nodeInfo, &defaultNodeInfo, sizeof(defaultNodeInfo));
 
     nodeInfo = &privconn->nodeInfo;
@@ -625,8 +631,12 @@ static int testOpenFromFile(virConnectPtr conn,
 
     str = virXPathString(conn, "string(/node/cpu/model[1])", ctxt);
     if (str != NULL) {
-        strncpy(nodeInfo->model, str, sizeof(nodeInfo->model)-1);
-        nodeInfo->model[sizeof(nodeInfo->model)-1] = '\0';
+        if (virStrcpyStatic(nodeInfo->model, str) == NULL) {
+            testError(NULL, VIR_ERR_INTERNAL_ERROR,
+                      _("Model %s too big for destination"), str);
+            VIR_FREE(str);
+            goto error;
+        }
         VIR_FREE(str);
     }
 
index 7db94e924a1f128bd7aac2ef54551cfe2bc18929..f0d5fd4640428c8e9c480022c68412e04b1dcc3a 100644 (file)
@@ -563,6 +563,7 @@ static int umlMonitorAddress(virConnectPtr conn,
                              virDomainObjPtr vm,
                              struct sockaddr_un *addr) {
     char *sockname;
+    int retval = 0;
 
     if (virAsprintf(&sockname, "%s/%s/mconsole",
                     driver->monitorDir, vm->def->name) < 0) {
@@ -572,10 +573,13 @@ static int umlMonitorAddress(virConnectPtr conn,
 
     memset(addr, 0, sizeof *addr);
     addr->sun_family = AF_UNIX;
-    strncpy(addr->sun_path, sockname, sizeof(addr->sun_path)-1);
-    NUL_TERMINATE(addr->sun_path);
+    if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
+        umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                       _("Unix path %s too long for destination"), sockname);
+        retval = -1;
+    }
     VIR_FREE(sockname);
-    return 0;
+    return retval;
 }
 
 static int umlOpenMonitor(virConnectPtr conn,
@@ -669,8 +673,11 @@ static int umlMonitorCommand(virConnectPtr conn,
                              cmd, req.length);
         return -1;
     }
-    strncpy(req.data, cmd, req.length);
-    req.data[req.length] = '\0';
+    if (virStrcpyStatic(req.data, cmd) == NULL) {
+        umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                       _("Command %s too long for destination"), cmd);
+        return -1;
+    }
 
     if (sendto(vm->monitor, &req, sizeof req, 0,
                (struct sockaddr *)&addr, sizeof addr) != (sizeof req)) {
index 414d87bc96e36bbd09d63c94b52743adc9255dc1..f9a7668bc86e2e4de20ac9e64d835d0ef32c3fc4 100644 (file)
@@ -149,23 +149,19 @@ brHasBridge(brControl *ctl,
             const char *name)
 {
     struct ifreq ifr;
-    int len;
 
     if (!ctl || !name) {
         errno = EINVAL;
         return -1;
     }
 
-    if ((len = strlen(name)) >= BR_IFNAME_MAXLEN) {
+    memset(&ifr, 0, sizeof(struct ifreq));
+
+    if (virStrcpyStatic(ifr.ifr_name, name) == NULL) {
         errno = EINVAL;
         return -1;
     }
 
-    memset(&ifr, 0, sizeof(struct ifreq));
-
-    strncpy(ifr.ifr_name, name, len);
-    ifr.ifr_name[len] = '\0';
-
     if (ioctl(ctl->fd, SIOCGIFFLAGS, &ifr))
         return -1;
 
@@ -216,18 +212,14 @@ brAddDelInterface(brControl *ctl,
                   const char *iface)
 {
     struct ifreq ifr;
-    int len;
 
     if (!ctl || !ctl->fd || !bridge || !iface)
         return EINVAL;
 
-    if ((len = strlen(bridge)) >= BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, bridge, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, bridge) == NULL)
+        return EINVAL;
 
     if (!(ifr.ifr_ifindex = if_nametoindex(iface)))
         return ENODEV;
@@ -305,23 +297,19 @@ brDeleteInterface(brControl *ctl ATTRIBUTE_UNUSED,
 static int ifGetMtu(brControl *ctl, const char *ifname)
 {
     struct ifreq ifr;
-    int len;
 
     if (!ctl || !ifname) {
         errno = EINVAL;
         return -1;
     }
 
-    if ((len = strlen(ifname)) >=  BR_IFNAME_MAXLEN) {
+    memset(&ifr, 0, sizeof(struct ifreq));
+
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL) {
         errno = EINVAL;
         return -1;
     }
 
-    memset(&ifr, 0, sizeof(struct ifreq));
-
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
-
     if (ioctl(ctl->fd, SIOCGIFMTU, &ifr))
         return -1;
 
@@ -343,18 +331,14 @@ static int ifGetMtu(brControl *ctl, const char *ifname)
 static int ifSetMtu(brControl *ctl, const char *ifname, int mtu)
 {
     struct ifreq ifr;
-    int len;
 
     if (!ctl || !ifname)
         return EINVAL;
 
-    if ((len = strlen(ifname)) >=  BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
+        return EINVAL;
     ifr.ifr_mtu = mtu;
 
     return ioctl(ctl->fd, SIOCSIFMTU, &ifr) == 0 ? 0 : errno;
@@ -466,7 +450,7 @@ brAddTap(brControl *ctl,
          int vnet_hdr,
          int *tapfd)
 {
-    int fd, len;
+    int fd;
     struct ifreq ifr;
 
     if (!ctl || !ctl->fd || !bridge || !ifname)
@@ -486,17 +470,14 @@ brAddTap(brControl *ctl,
     (void) vnet_hdr;
 #endif
 
-    strncpy(ifr.ifr_name, *ifname, IFNAMSIZ-1);
-
-    if (ioctl(fd, TUNSETIFF, &ifr) < 0)
-        goto error;
-
-    len = strlen(ifr.ifr_name);
-    if (len >= BR_IFNAME_MAXLEN - 1) {
+    if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
         errno = EINVAL;
         goto error;
     }
 
+    if (ioctl(fd, TUNSETIFF, &ifr) < 0)
+        goto error;
+
     /* We need to set the interface MTU before adding it
      * to the bridge, because the bridge will have its
      * MTU adjusted automatically when we add the new interface.
@@ -527,7 +508,6 @@ int brDeleteTap(brControl *ctl,
                 const char *ifname)
 {
     struct ifreq try;
-    int len;
     int fd;
 
     if (!ctl || !ctl->fd || !ifname)
@@ -539,15 +519,11 @@ int brDeleteTap(brControl *ctl,
     memset(&try, 0, sizeof(struct ifreq));
     try.ifr_flags = IFF_TAP|IFF_NO_PI;
 
-    len = strlen(ifname);
-    if (len >= BR_IFNAME_MAXLEN - 1) {
+    if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
         errno = EINVAL;
         goto error;
     }
 
-    strncpy(try.ifr_name, ifname, len);
-    try.ifr_name[len] = '\0';
-
     if (ioctl(fd, TUNSETIFF, &try) == 0) {
         if ((errno = ioctl(fd, TUNSETPERSIST, 0)))
             goto error;
@@ -576,19 +552,15 @@ brSetInterfaceUp(brControl *ctl,
                  int up)
 {
     struct ifreq ifr;
-    int len;
     int flags;
 
     if (!ctl || !ifname)
         return EINVAL;
 
-    if ((len = strlen(ifname)) >= BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
+        return EINVAL;
 
     if (ioctl(ctl->fd, SIOCGIFFLAGS, &ifr) < 0)
         return errno;
@@ -621,18 +593,14 @@ brGetInterfaceUp(brControl *ctl,
                  int *up)
 {
     struct ifreq ifr;
-    int len;
 
     if (!ctl || !ifname || !up)
         return EINVAL;
 
-    if ((len = strlen(ifname)) >= BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
+        return EINVAL;
 
     if (ioctl(ctl->fd, SIOCGIFFLAGS, &ifr) < 0)
         return errno;
@@ -654,18 +622,15 @@ brSetInetAddr(brControl *ctl,
     } s;
     struct ifreq ifr;
     struct in_addr inaddr;
-    int len, ret;
+    int ret;
 
     if (!ctl || !ctl->fd || !ifname || !addr)
         return EINVAL;
 
-    if ((len = strlen(ifname)) >= BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
+        return EINVAL;
 
     if ((ret = inet_pton(AF_INET, addr, &inaddr)) < 0)
         return errno;
@@ -692,18 +657,14 @@ brGetInetAddr(brControl *ctl,
 {
     struct ifreq ifr;
     struct in_addr *inaddr;
-    int len;
 
     if (!ctl || !ctl->fd || !ifname || !addr)
         return EINVAL;
 
-    if ((len = strlen(ifname)) >= BR_IFNAME_MAXLEN)
-        return EINVAL;
-
     memset(&ifr, 0, sizeof(struct ifreq));
 
-    strncpy(ifr.ifr_name, ifname, len);
-    ifr.ifr_name[len] = '\0';
+    if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
+        return EINVAL;
 
     if (ioctl(ctl->fd, cmd, &ifr) < 0)
         return errno;
index 1878e33cac6099e880d6f1dcc5ac26b3229d69a0..ef07a6a57c037549e83e448428ed70c2835270e5 100644 (file)
@@ -1123,9 +1123,8 @@ char *virFindFileInPath(const char *file)
     char fullpath[PATH_MAX];
 
     /* copy PATH env so we can tweak it */
-    strncpy(pathenv, getenv("PATH"), PATH_MAX);
-    pathenv[PATH_MAX - 1] = '\0';
-
+    if (virStrcpyStatic(pathenv, getenv("PATH")) == NULL)
+        return NULL;
 
     /* for each path segment, append the file to search for and test for
      * it. return it if found.
@@ -1157,8 +1156,8 @@ int virFileMakePath(const char *path)
     if (stat(path, &st) >= 0)
         return 0;
 
-    strncpy(parent, path, PATH_MAX);
-    parent[PATH_MAX - 1] = '\0';
+    if (virStrcpyStatic(parent, path) == NULL)
+        return EINVAL;
 
     if (!(p = strrchr(parent, '/')))
         return EINVAL;
@@ -1575,6 +1574,49 @@ virAsprintf(char **strp, const char *fmt, ...)
     return ret;
 }
 
+/**
+ * virStrncpy
+ *
+ * A safe version of strncpy.  The last parameter is the number of bytes
+ * available in the destination string, *not* the number of bytes you want
+ * to copy.  If the destination is not large enough to hold all n of the
+ * src string bytes plus a \0, NULL is returned and no data is copied.
+ * If the destination is large enough to hold the n bytes plus \0, then the
+ * string is copied and a pointer to the destination string is returned.
+ */
+char *
+virStrncpy(char *dest, const char *src, size_t n, size_t destbytes)
+{
+    char *ret;
+
+    if (n > (destbytes - 1))
+        return NULL;
+
+    ret = strncpy(dest, src, n);
+    /* strncpy NULL terminates iff the last character is \0.  Therefore
+     * force the last byte to be \0
+     */
+    dest[n] = '\0';
+
+    return ret;
+}
+
+/**
+ * virStrcpy
+ *
+ * A safe version of strcpy.  The last parameter is the number of bytes
+ * available in the destination string, *not* the number of bytes you want
+ * to copy.  If the destination is not large enough to hold all n of the
+ * src string bytes plus a \0, NULL is returned and no data is copied.
+ * If the destination is large enough to hold the source plus \0, then the
+ * string is copied and a pointer to the destination string is returned.
+ */
+char *
+virStrcpy(char *dest, const char *src, size_t destbytes)
+{
+    return virStrncpy(dest, src, strlen(src), destbytes);
+}
+
 /* Compare two MAC addresses, ignoring differences in case,
  * as well as leading zeros.
  */
index f9715ab52bb1a3bb47e8d6ce615720874a60edfd..dbfdc45c2d0e1f87e688ea21cbb9f8f6e3c4276d 100644 (file)
@@ -164,6 +164,11 @@ void virSkipSpaces(const char **str);
 int virParseNumber(const char **str);
 int virAsprintf(char **strp, const char *fmt, ...)
     ATTRIBUTE_FMT_PRINTF(2, 3);
+char *virStrncpy(char *dest, const char *src, size_t n, size_t destbytes)
+    ATTRIBUTE_RETURN_CHECK;
+char *virStrcpy(char *dest, const char *src, size_t destbytes)
+    ATTRIBUTE_RETURN_CHECK;
+#define virStrcpyStatic(dest, src) virStrcpy((dest), (src), sizeof(dest))
 
 #define VIR_MAC_BUFLEN 6
 #define VIR_MAC_PREFIX_BUFLEN 3
index 49127d7cf229bf779fac1f2186c42ef41c0be0f8..f9d2fade1f3c031e9f5e50fef5761597845dc36a 100644 (file)
@@ -197,7 +197,10 @@ retry:
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
     addr.sun_path[0] = '\0';
-    strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
+    if (virStrcpy(&addr.sun_path[1], path, sizeof(addr.sun_path) - 1) == NULL) {
+        close(fd);
+        return -1;
+    }
 
     /*
      * now bind the socket to that address and listen on it
index 9f3f5fe797ce8445b12626d004cbe8bde1058b1f..3aa3c30be5aaa4728e51e85db360e1cacaf0fb97 100644 (file)
@@ -1209,13 +1209,19 @@ xenHypervisorGetSchedulerParameters(virDomainPtr domain,
                 if (ret < 0)
                     return(-1);
 
-                strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-                params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+                if (virStrcpyStatic(params[0].field, str_weight) == NULL) {
+                    virXenError (domain->conn, VIR_ERR_INTERNAL_ERROR,
+                                 "Weight %s too big for destination", str_weight);
+                    return -1;
+                }
                 params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
                 params[0].value.ui = op_dom.u.getschedinfo.u.credit.weight;
 
-                strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-                params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+                if (virStrcpyStatic(params[1].field, str_cap) == NULL) {
+                    virXenError (domain->conn, VIR_ERR_INTERNAL_ERROR,
+                                 "Cap %s too big for destination", str_cap);
+                    return -1;
+                }
                 params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
                 params[1].value.ui = op_dom.u.getschedinfo.u.credit.cap;
 
@@ -2427,9 +2433,11 @@ xenHypervisorMakeCapabilitiesInternal(virConnectPtr conn,
         while (fgets (line, sizeof line, cpuinfo)) {
             if (regexec (&flags_hvm_rec, line, sizeof(subs)/sizeof(regmatch_t), subs, 0) == 0
                 && subs[0].rm_so != -1) {
-                strncpy (hvm_type,
-                         &line[subs[1].rm_so], subs[1].rm_eo-subs[1].rm_so+1);
-                hvm_type[subs[1].rm_eo-subs[1].rm_so] = '\0';
+                if (virStrncpy(hvm_type,
+                               &line[subs[1].rm_so],
+                               subs[1].rm_eo-subs[1].rm_so,
+                               sizeof(hvm_type)) == NULL)
+                    return NULL;
             } else if (regexec (&flags_pae_rec, line, 0, NULL, 0) == 0)
                 host_pae = 1;
         }
index 350ef8ce1355935617da6f533d33f5314300436f..49bdba9015622510999756b0439fc18ca55df520 100644 (file)
@@ -763,7 +763,8 @@ xenDaemonOpen_unix(virConnectPtr conn, const char *path)
     addr = (struct sockaddr_un *)&priv->addr;
     addr->sun_family = AF_UNIX;
     memset(addr->sun_path, 0, sizeof(addr->sun_path));
-    strncpy(addr->sun_path, path, sizeof(addr->sun_path));
+    if (virStrcpyStatic(addr->sun_path, path) == NULL)
+        return -1;
 
     return (0);
 }
@@ -1433,7 +1434,7 @@ xenDaemonParseSxprChar(virConnectPtr conn,
                        const char *value,
                        const char *tty)
 {
-    char prefix[10];
+    const char *prefix;
     char *tmp;
     virDomainChrDefPtr def;
 
@@ -1442,18 +1443,17 @@ xenDaemonParseSxprChar(virConnectPtr conn,
         return NULL;
     }
 
-    strncpy(prefix, value, sizeof(prefix)-1);
-    NUL_TERMINATE(prefix);
+    prefix = value;
 
     if (value[0] == '/') {
         def->type = VIR_DOMAIN_CHR_TYPE_DEV;
     } else {
-        if ((tmp = strchr(prefix, ':')) != NULL) {
+        if ((tmp = strchr(value, ':')) != NULL) {
             *tmp = '\0';
-            value += (tmp - prefix) + 1;
+            value = tmp + 1;
         }
 
-        if (STREQ(prefix, "telnet")) {
+        if (STRPREFIX(prefix, "telnet")) {
             def->type = VIR_DOMAIN_CHR_TYPE_TCP;
             def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
         } else {
@@ -1647,8 +1647,13 @@ xenDaemonParseSxprDisks(virConnectPtr conn,
 
                 if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
                     goto no_memory;
-                strncpy(disk->driverName, src, (offset-src));
-                disk->driverName[offset-src] = '\0';
+                if (virStrncpy(disk->driverName, src, offset-src,
+                              (offset-src)+1) == NULL) {
+                    virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 _("Driver name %s too big for destination"),
+                                 src);
+                    goto error;
+                }
 
                 src = offset + 1;
 
@@ -1662,8 +1667,13 @@ xenDaemonParseSxprDisks(virConnectPtr conn,
 
                     if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
                         goto no_memory;
-                    strncpy(disk->driverType, src, (offset-src));
-                    disk->driverType[offset-src] = '\0';
+                    if (virStrncpy(disk->driverType, src, offset-src,
+                                   (offset-src)+1) == NULL) {
+                        virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+                                     _("Driver type %s too big for destination"),
+                                     src);
+                        goto error;
+                    }
 
                     src = offset + 1;
                     /* Its possible to use blktap driver for block devs
@@ -1891,13 +1901,12 @@ xenDaemonParseSxprSound(virConnectPtr conn,
                 len = (offset2 - offset);
             else
                 len = strlen(offset);
-            if (len > (sizeof(model)-1)) {
+            if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
                 virXendError(conn, VIR_ERR_INTERNAL_ERROR,
-                                 _("unexpected sound model %s"), offset);
+                                 _("Sound model %s too big for destination"),
+                             offset);
                 goto error;
             }
-            strncpy(model, offset, len);
-            model[len] = '\0';
 
             if (VIR_ALLOC(sound) < 0)
                 goto no_memory;
@@ -4798,13 +4807,20 @@ xenDaemonGetSchedulerParameters(virDomainPtr domain,
                 goto error;
             }
 
-            strncpy (params[0].field, str_weight, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-            params[0].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+            if (virStrcpyStatic(params[0].field, str_weight) == NULL) {
+                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                             _("Weight %s too big for destination"),
+                             str_weight);
+                goto error;
+            }
             params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT;
             params[0].value.ui = sexpr_int(root, "domain/cpu_weight");
 
-            strncpy (params[1].field, str_cap, VIR_DOMAIN_SCHED_FIELD_LENGTH);
-            params[1].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
+            if (virStrcpyStatic(params[1].field, str_cap) == NULL) {
+                virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
+                             _("Cap %s too big for destination"), str_cap);
+                goto error;
+            }
             params[1].type = VIR_DOMAIN_SCHED_FIELD_UINT;
             params[1].value.ui = sexpr_int(root, "domain/cpu_cap");
             *nparams = XEN_SCHED_CRED_NPARAM;
@@ -5860,6 +5876,7 @@ virDomainXMLDevID(virDomainPtr domain,
 {
     xenUnifiedPrivatePtr priv = domain->conn->privateData;
     char *xref;
+    char *tmp;
 
     if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
         if (dev->data.disk->driverName &&
@@ -5877,9 +5894,10 @@ virDomainXMLDevID(virDomainPtr domain,
         if (xref == NULL)
             return -1;
 
-        strncpy(ref, xref, ref_len);
+        tmp = virStrcpy(ref, xref, ref_len);
         free(xref);
-        ref[ref_len - 1] = '\0';
+        if (tmp == NULL)
+            return -1;
     } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
         char mac[30];
         virDomainNetDefPtr def = dev->data.net;
@@ -5896,9 +5914,10 @@ virDomainXMLDevID(virDomainPtr domain,
         if (xref == NULL)
             return -1;
 
-        strncpy(ref, xref, ref_len);
+        tmp = virStrcpy(ref, xref, ref_len);
         free(xref);
-        ref[ref_len - 1] = '\0';
+        if (tmp == NULL)
+            return -1;
     } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
                dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
                dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
index 960b17af3d09864e65e742c0303c8bce778c248d..9c78f0defb98657e693e815c725bea789e7727f8 100644 (file)
@@ -872,8 +872,13 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
             } else {
                 if (VIR_ALLOC_N(disk->src, (offset - head) + 1) < 0)
                     goto no_memory;
-                strncpy(disk->src, head, (offset - head));
-                disk->src[(offset-head)] = '\0';
+                if (virStrncpy(disk->src, head, offset - head,
+                               (offset - head) + 1) == NULL) {
+                    xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                               _("Source file %s too big for destination"),
+                               head);
+                    goto cleanup;
+                }
             }
             head = offset + 1;
 
@@ -886,8 +891,12 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
                 goto skipdisk;
             if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
                 goto no_memory;
-            strncpy(disk->dst, head, (offset - head));
-            disk->dst[(offset-head)] = '\0';
+            if (virStrncpy(disk->dst, head, offset - head,
+                           (offset - head) + 1) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("Dest file %s too big for destination"), head);
+                goto cleanup;
+            }
             head = offset + 1;
 
 
@@ -897,8 +906,14 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
                 if ((tmp = strchr(disk->src, ':')) != NULL) {
                     if (VIR_ALLOC_N(disk->driverName, (tmp - disk->src) + 1) < 0)
                         goto no_memory;
-                    strncpy(disk->driverName, disk->src, (tmp - disk->src));
-                    disk->driverName[tmp - disk->src] = '\0';
+                    if (virStrncpy(disk->driverName, disk->src,
+                                   (tmp - disk->src),
+                                   (tmp - disk->src) + 1) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Driver name %s too big for destination"),
+                                   disk->src);
+                        goto cleanup;
+                    }
 
                     /* Strip the prefix we found off the source file name */
                     memmove(disk->src, disk->src+(tmp-disk->src)+1,
@@ -912,8 +927,14 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
                         goto skipdisk;
                     if (VIR_ALLOC_N(disk->driverType, (tmp - disk->src) + 1) < 0)
                         goto no_memory;
-                    strncpy(disk->driverType, disk->src, (tmp - disk->src));
-                    disk->driverType[tmp - disk->src] = '\0';
+                    if (virStrncpy(disk->driverType, disk->src,
+                                   (tmp - disk->src),
+                                   (tmp - disk->src) + 1) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Driver type %s too big for destination"),
+                                   disk->src);
+                        goto cleanup;
+                    }
 
                     /* Strip the prefix we found off the source file name */
                     memmove(disk->src, disk->src+(tmp-disk->src)+1,
@@ -1023,41 +1044,51 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
                 data++;
 
                 if (STRPREFIX(key, "mac=")) {
-                    int len = nextkey ? (nextkey - data) : 17;
-                    if (len > 17)
-                        len = 17;
-                    strncpy(mac, data, len);
-                    mac[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(mac) - 1;
+                    if (virStrncpy(mac, data, len, sizeof(mac)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("MAC address %s too big for destination"),
+                                   data);
+                        goto skipnic;
+                    }
                 } else if (STRPREFIX(key, "bridge=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(bridge)-1;
-                    if (len > (sizeof(bridge)-1))
-                        len = sizeof(bridge)-1;
-                    strncpy(bridge, data, len);
-                    bridge[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(bridge) - 1;
+                    if (virStrncpy(bridge, data, len, sizeof(bridge)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Bridge %s too big for destination"),
+                                   data);
+                        goto skipnic;
+                    }
                 } else if (STRPREFIX(key, "script=")) {
-                    int len = nextkey ? (nextkey - data) : PATH_MAX-1;
-                    if (len > (PATH_MAX-1))
-                        len = PATH_MAX-1;
-                    strncpy(script, data, len);
-                    script[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(script) - 1;
+                    if (virStrncpy(script, data, len, sizeof(script)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Script %s too big for destination"),
+                                   data);
+                        goto skipnic;
+                    }
                 } else if (STRPREFIX(key, "model=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(model)-1;
-                    if (len > (sizeof(model)-1))
-                        len = sizeof(model)-1;
-                    strncpy(model, data, len);
-                    model[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(model) - 1;
+                    if (virStrncpy(model, data, len, sizeof(model)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Model %s too big for destination"), data);
+                        goto skipnic;
+                    }
                 } else if (STRPREFIX(key, "vifname=")) {
-                    int len = nextkey ? (nextkey - data) : sizeof(vifname)-1;
-                    if (len > (sizeof(vifname)-1))
-                        len = sizeof(vifname)-1;
-                    strncpy(vifname, data, len);
-                    vifname[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(vifname) - 1;
+                    if (virStrncpy(vifname, data, len, sizeof(vifname)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("Vifname %s too big for destination"),
+                                   data);
+                        goto skipnic;
+                    }
                 } else if (STRPREFIX(key, "ip=")) {
-                    int len = nextkey ? (nextkey - data) : 15;
-                    if (len > 15)
-                        len = 15;
-                    strncpy(ip, data, len);
-                    ip[len] = '\0';
+                    int len = nextkey ? (nextkey - data) : sizeof(ip) - 1;
+                    if (virStrncpy(ip, data, len, sizeof(ip)) == NULL) {
+                        xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                                   _("IP %s too big for destination"), data);
+                        goto skipnic;
+                    }
                 }
 
                 while (nextkey && (nextkey[0] == ',' ||
@@ -1156,32 +1187,41 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
             if (!(nextkey = strchr(key, ':')))
                 goto skippci;
 
-            if ((nextkey - key) > (sizeof(domain)-1))
+            if (virStrncpy(domain, key, (nextkey - key), sizeof(domain)) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("Domain %s too big for destination"), key);
                 goto skippci;
-
-            strncpy(domain, key, sizeof(domain));
-            domain[sizeof(domain)-1] = '\0';
+            }
 
             key = nextkey + 1;
             if (!(nextkey = strchr(key, ':')))
                 goto skippci;
 
-            strncpy(bus, key, sizeof(bus));
-            bus[sizeof(bus)-1] = '\0';
+            if (virStrncpy(bus, key, (nextkey - key), sizeof(bus)) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("Bus %s too big for destination"), key);
+                goto skippci;
+            }
 
             key = nextkey + 1;
             if (!(nextkey = strchr(key, '.')))
                 goto skippci;
 
-            strncpy(slot, key, sizeof(slot));
-            slot[sizeof(slot)-1] = '\0';
+            if (virStrncpy(slot, key, (nextkey - key), sizeof(slot)) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("Slot %s too big for destination"), key);
+                goto skippci;
+            }
 
             key = nextkey + 1;
             if (strlen(key) != 1)
                 goto skippci;
 
-            strncpy(func, key, sizeof(func));
-            func[sizeof(func)-1] = '\0';
+            if (virStrncpy(func, key, 1, sizeof(func)) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("Function %s too big for destination"), key);
+                goto skippci;
+            }
 
             if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
                 goto skippci;
@@ -1292,8 +1332,13 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) {
             list->list->str) {
             char vfb[MAX_VFB];
             char *key = vfb;
-            strncpy(vfb, list->list->str, MAX_VFB-1);
-            vfb[MAX_VFB-1] = '\0';
+
+            if (virStrcpyStatic(vfb, list->list->str) == NULL) {
+                xenXMError(conn, VIR_ERR_INTERNAL_ERROR,
+                           _("VFB %s too big for destination"),
+                           list->list->str);
+                goto cleanup;
+            }
 
             if (VIR_ALLOC(graphics) < 0)
                 goto no_memory;