+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
=============================
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 \
$(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
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)
/* 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:
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
#include "logging.h"
#include "memory.h"
#include "uuid.h"
+#include "util.h"
#define VIR_FROM_THIS VIR_FROM_NONE
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;
++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);
}
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;
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,
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",
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;
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 */
#include <fcntl.h>
#include <unistd.h>
#include "one_client.h"
+#include "datatypes.h"
+#include "util.h"
oneClient one_client;
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;
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);
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;
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;
"%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"));
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;
}
}
char uuidbuf[1024];
char iden[1024];
int fd, ret;
+ int retval = 0;
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
return -1;
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,
}
temp_buffer[j] = '\0';
- if (strncpy(dst, temp_buffer, dstlen) == NULL)
+ if (virStrcpy(dst, temp_buffer, dstlen) == NULL)
return -1;
return 0;
{
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:
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:
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));
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;
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';
(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;
/* 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:
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 {
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;
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);
}
virDomainObjPtr vm,
struct sockaddr_un *addr) {
char *sockname;
+ int retval = 0;
if (virAsprintf(&sockname, "%s/%s/mconsole",
driver->monitorDir, vm->def->name) < 0) {
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,
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)) {
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;
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;
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;
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;
int vnet_hdr,
int *tapfd)
{
- int fd, len;
+ int fd;
struct ifreq ifr;
if (!ctl || !ctl->fd || !bridge || !ifname)
(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.
const char *ifname)
{
struct ifreq try;
- int len;
int fd;
if (!ctl || !ctl->fd || !ifname)
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;
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;
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;
} 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;
{
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;
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.
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;
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.
*/
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
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
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;
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;
}
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);
}
const char *value,
const char *tty)
{
- char prefix[10];
+ const char *prefix;
char *tmp;
virDomainChrDefPtr def;
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 {
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;
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
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;
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;
{
xenUnifiedPrivatePtr priv = domain->conn->privateData;
char *xref;
+ char *tmp;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
if (dev->data.disk->driverName &&
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;
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) {
} 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;
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;
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,
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,
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] == ',' ||
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;
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;