Similarly to VIR_STRDUP, we want the OOM error to be reported in VIR_ALLOC and friends. --- po/POTFILES.in | 1 + python/libvirt-override.c | 102 +++++++++---------- src/conf/domain_conf.c | 9 +- src/conf/network_conf.c | 34 ++----- src/conf/node_device_conf.c | 2 +- src/esx/esx_vi.c | 2 +- src/lxc/lxc_process.c | 4 +- src/security/security_manager.c | 4 +- src/security/security_selinux.c | 4 +- src/util/viralloc.c | 165 ++++++++++++++++++++++++++----- src/util/viralloc.h | 213 ++++++++++++++++++++++++++++++++-------- src/util/virbuffer.c | 8 +- src/util/vircgroup.c | 2 +- src/util/virerror.c | 4 +- src/util/virpci.c | 2 +- src/util/virthreadpthread.c | 2 +- tests/commandhelper.c | 1 + tests/networkxml2conftest.c | 2 + tests/test_conf.c | 2 +- tests/xmconfigtest.c | 2 + 20 files changed, 401 insertions(+), 164 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index af7fd7f..0b65765 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -141,6 +141,7 @@ src/test/test_driver.c src/uml/uml_conf.c src/uml/uml_driver.c src/util/iohelper.c +src/util/viralloc.c src/util/viraudit.c src/util/virauth.c src/util/virauthconfig.c diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 5c5586d..6b6e77b 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -171,7 +171,7 @@ setPyVirTypedParameter(PyObject *info, return NULL; } - if (VIR_ALLOC_N(ret, size) < 0) { + if (VIR_ALLOC_N_QUIET(ret, size) < 0) { PyErr_NoMemory(); return NULL; } @@ -511,7 +511,7 @@ libvirt_virDomainBlockStatsFlags(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -577,7 +577,7 @@ libvirt_virDomainGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) sumparams = nparams * MIN(ncpus, 128); - if (VIR_ALLOC_N(params, sumparams) < 0) { + if (VIR_ALLOC_N_QUIET(params, sumparams) < 0) { error = PyErr_NoMemory(); goto error; } @@ -629,7 +629,7 @@ libvirt_virDomainGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) if (nparams) { sumparams = nparams; - if (VIR_ALLOC_N(params, nparams) < 0) { + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) { error = PyErr_NoMemory(); goto error; } @@ -809,7 +809,7 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -857,7 +857,7 @@ libvirt_virDomainGetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -917,7 +917,7 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -993,7 +993,7 @@ libvirt_virDomainSetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1067,7 +1067,7 @@ libvirt_virDomainSetBlkioParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1127,7 +1127,7 @@ libvirt_virDomainGetBlkioParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1187,7 +1187,7 @@ libvirt_virDomainSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1247,7 +1247,7 @@ libvirt_virDomainGetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1307,7 +1307,7 @@ libvirt_virDomainSetNumaParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1367,7 +1367,7 @@ libvirt_virDomainGetNumaParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1428,7 +1428,7 @@ libvirt_virDomainSetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1489,7 +1489,7 @@ libvirt_virDomainGetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1535,12 +1535,12 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, if (i_retval < 0) return VIR_PY_INT_FAIL; - if (VIR_ALLOC_N(cpuinfo, dominfo.nrVirtCpu) < 0) + if (VIR_ALLOC_N_QUIET(cpuinfo, dominfo.nrVirtCpu) < 0) return PyErr_NoMemory(); cpumaplen = VIR_CPU_MAPLEN(cpunum); if (xalloc_oversized(dominfo.nrVirtCpu, cpumaplen) || - VIR_ALLOC_N(cpumap, dominfo.nrVirtCpu * cpumaplen) < 0) { + VIR_ALLOC_N_QUIET(cpumap, dominfo.nrVirtCpu * cpumaplen) < 0) { error = PyErr_NoMemory(); goto cleanup; } @@ -1662,7 +1662,7 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, } cpumaplen = VIR_CPU_MAPLEN(cpunum); - if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) + if (VIR_ALLOC_N_QUIET(cpumap, cpumaplen) < 0) return PyErr_NoMemory(); for (i = 0; i < tuple_size; i++) { @@ -1726,7 +1726,7 @@ libvirt_virDomainPinVcpuFlags(PyObject *self ATTRIBUTE_UNUSED, } cpumaplen = VIR_CPU_MAPLEN(cpunum); - if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) + if (VIR_ALLOC_N_QUIET(cpumap, cpumaplen) < 0) return PyErr_NoMemory(); for (i = 0; i < tuple_size; i++) { @@ -1786,7 +1786,7 @@ libvirt_virDomainGetVcpuPinInfo(PyObject *self ATTRIBUTE_UNUSED, cpumaplen = VIR_CPU_MAPLEN(cpunum); if (xalloc_oversized(dominfo.nrVirtCpu, cpumaplen) || - VIR_ALLOC_N(cpumaps, dominfo.nrVirtCpu * cpumaplen) < 0) + VIR_ALLOC_N_QUIET(cpumaps, dominfo.nrVirtCpu * cpumaplen) < 0) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -1854,7 +1854,7 @@ libvirt_virDomainPinEmulator(PyObject *self ATTRIBUTE_UNUSED, if ((tuple_size = PyTuple_Size(pycpumap)) == -1) return NULL; - if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) + if (VIR_ALLOC_N_QUIET(cpumap, cpumaplen) < 0) return PyErr_NoMemory(); for (i = 0; i < tuple_size; i++) { @@ -1913,7 +1913,7 @@ libvirt_virDomainGetEmulatorPinInfo(PyObject *self ATTRIBUTE_UNUSED, cpumaplen = VIR_CPU_MAPLEN(cpunum); - if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) + if (VIR_ALLOC_N_QUIET(cpumap, cpumaplen) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -2188,7 +2188,7 @@ libvirt_virConnectOpenAuth(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { auth.ncredtype = PyList_Size(pycredtype); if (auth.ncredtype) { int i; - if (VIR_ALLOC_N(auth.credtype, auth.ncredtype) < 0) + if (VIR_ALLOC_N_QUIET(auth.credtype, auth.ncredtype) < 0) return VIR_PY_NONE; for (i = 0; i < auth.ncredtype; i++) { PyObject *val; @@ -2316,7 +2316,7 @@ libvirt_virConnectListDomainsID(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(ids, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(ids, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -2407,7 +2407,7 @@ libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedDomains(conn, names, c_retval); @@ -2454,7 +2454,7 @@ libvirt_virDomainSnapshotListNames(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotListNames(dom, names, c_retval, flags); @@ -2554,7 +2554,7 @@ libvirt_virDomainSnapshotListChildrenNames(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotListChildrenNames(snap, names, c_retval, @@ -2886,7 +2886,7 @@ libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNetworks(conn, names, c_retval); @@ -2931,7 +2931,7 @@ libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedNetworks(conn, names, c_retval); @@ -3139,7 +3139,7 @@ libvirt_virNodeGetCellsFreeMemory(PyObject *self ATTRIBUTE_UNUSED, PyObject *arg return VIR_PY_NONE; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); - if (VIR_ALLOC_N(freeMems, maxCells) < 0) + if (VIR_ALLOC_N_QUIET(freeMems, maxCells) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -3183,7 +3183,7 @@ libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return VIR_PY_NONE; if (nparams) { - if (VIR_ALLOC_N(stats, nparams) < 0) + if (VIR_ALLOC_N_QUIET(stats, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -3246,7 +3246,7 @@ libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return VIR_PY_NONE; if (nparams) { - if (VIR_ALLOC_N(stats, nparams) < 0) + if (VIR_ALLOC_N_QUIET(stats, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -3306,7 +3306,7 @@ libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListStoragePools(conn, names, c_retval); @@ -3359,7 +3359,7 @@ libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedStoragePools(conn, names, c_retval); @@ -3458,7 +3458,7 @@ libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolListVolumes(pool, names, c_retval); @@ -3719,7 +3719,7 @@ libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeListDevices(conn, cap, names, c_retval, flags); @@ -3809,7 +3809,7 @@ libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceListCaps(dev, names, c_retval); @@ -3928,7 +3928,7 @@ libvirt_virConnectListSecrets(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(uuids, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(uuids, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListSecrets(conn, uuids, c_retval); @@ -4147,7 +4147,7 @@ libvirt_virConnectListNWFilters(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(uuids, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(uuids, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNWFilters(conn, uuids, c_retval); @@ -4238,7 +4238,7 @@ libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListInterfaces(conn, names, c_retval); @@ -4292,7 +4292,7 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_NONE; if (c_retval) { - if (VIR_ALLOC_N(names, c_retval) < 0) + if (VIR_ALLOC_N_QUIET(names, c_retval) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedInterfaces(conn, names, c_retval); @@ -4392,7 +4392,7 @@ libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED, int i; ncpus = PyList_Size(list); - if (VIR_ALLOC_N(xmlcpus, ncpus) < 0) + if (VIR_ALLOC_N_QUIET(xmlcpus, ncpus) < 0) return VIR_PY_INT_FAIL; for (i = 0; i < ncpus; i++) { @@ -4578,7 +4578,7 @@ libvirt_virDomainSetBlockIoTune(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -4639,7 +4639,7 @@ libvirt_virDomainGetBlockIoTune(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -4682,7 +4682,7 @@ libvirt_virDomainGetDiskErrors(PyObject *self ATTRIBUTE_UNUSED, ndisks = count; if (ndisks) { - if (VIR_ALLOC_N(disks, ndisks) < 0) + if (VIR_ALLOC_N_QUIET(disks, ndisks) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -6503,7 +6503,7 @@ libvirt_virStreamRecv(PyObject *self ATTRIBUTE_UNUSED, } stream = PyvirStream_Get(pyobj_stream); - if (VIR_ALLOC_N(buf, nbytes+1 > 0 ? nbytes+1 : 1) < 0) + if (VIR_ALLOC_N_QUIET(buf, nbytes+1 > 0 ? nbytes+1 : 1) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -6729,7 +6729,7 @@ libvirt_virDomainBlockPeek(PyObject *self ATTRIBUTE_UNUSED, domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); - if (VIR_ALLOC_N(buf, size) < 0) + if (VIR_ALLOC_N_QUIET(buf, size) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -6766,7 +6766,7 @@ libvirt_virDomainMemoryPeek(PyObject *self ATTRIBUTE_UNUSED, domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); - if (VIR_ALLOC_N(buf, size) < 0) + if (VIR_ALLOC_N_QUIET(buf, size) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; @@ -6826,7 +6826,7 @@ libvirt_virNodeSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, return NULL; } - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; @@ -6886,7 +6886,7 @@ libvirt_virNodeGetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, if (!nparams) return PyDict_New(); - if (VIR_ALLOC_N(params, nparams) < 0) + if (VIR_ALLOC_N_QUIET(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f80b690..921a4f6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2750,8 +2750,8 @@ virDomainDefPostParseInternal(virDomainDefPtr def, /* create the serial port definition from the console definition */ if (def->nserials == 0) { if (VIR_APPEND_ELEMENT(def->serials, def->nserials, - def->consoles[0]) < 0) - goto no_memory; + def->consoles[0], true) < 0) + return -1; /* modify it to be a serial port */ def->serials[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; @@ -10435,9 +10435,8 @@ virDomainDefMaybeAddController(virDomainDefPtr def, cont->opts.vioserial.vectors = -1; } - if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, cont) < 0) { + if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, cont, true) < 0) { VIR_FREE(cont); - virReportOOMError(); return -1; } @@ -11907,7 +11906,7 @@ virDomainDefParseXML(xmlDocPtr xml, if (VIR_INSERT_ELEMENT_INPLACE(def->videos, ii, def->nvideos, - video) < 0) { + video, false) < 0) { virDomainVideoDefFree(video); goto error; } diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 64fd581..d6799d2 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -3414,10 +3414,8 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def, if (VIR_INSERT_ELEMENT(ipdef->hosts, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ? 0 : ipdef->nhosts, - ipdef->nhosts, host) < 0) { - virReportOOMError(); + ipdef->nhosts, host, true) < 0) goto cleanup; - } } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (virNetworkDHCPHostDefParseXML(def->name, ipdef, @@ -3520,11 +3518,8 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, if (VIR_INSERT_ELEMENT(ipdef->ranges, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ? 0 : ipdef->nranges, - ipdef->nranges, range) < 0) { - virReportOOMError(); + ipdef->nranges, range, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (ii == ipdef->nranges) { @@ -3615,11 +3610,8 @@ virNetworkDefUpdateForwardInterface(virNetworkDefPtr def, if (VIR_INSERT_ELEMENT(def->forward.ifs, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ? 0 : def->forward.nifs, - def->forward.nifs, iface) < 0) { - virReportOOMError(); + def->forward.nifs, iface, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (ii == def->forward.nifs) { @@ -3742,11 +3734,8 @@ virNetworkDefUpdatePortGroup(virNetworkDefPtr def, if (VIR_INSERT_ELEMENT(def->portGroups, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ? 0 : def->nPortGroups, - def->nPortGroups, portgroup) < 0) { - virReportOOMError(); + def->nPortGroups, portgroup, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { /* remove it */ @@ -3825,11 +3814,8 @@ virNetworkDefUpdateDNSHost(virNetworkDefPtr def, /* add to beginning/end of list */ if (VIR_INSERT_ELEMENT(dns->hosts, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST - ? 0 : dns->nhosts, dns->nhosts, host) < 0) { - virReportOOMError(); + ? 0 : dns->nhosts, dns->nhosts, host, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (foundCt == 0) { @@ -3913,11 +3899,8 @@ virNetworkDefUpdateDNSSrv(virNetworkDefPtr def, /* add to beginning/end of list */ if (VIR_INSERT_ELEMENT(dns->srvs, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST - ? 0 : dns->nsrvs, dns->nsrvs, srv) < 0) { - virReportOOMError(); + ? 0 : dns->nsrvs, dns->nsrvs, srv, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (foundCt == 0) { @@ -3995,11 +3978,8 @@ virNetworkDefUpdateDNSTxt(virNetworkDefPtr def, /* add to beginning/end of list */ if (VIR_INSERT_ELEMENT(dns->txts, command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST - ? 0 : dns->ntxts, dns->ntxts, txt) < 0) { - virReportOOMError(); + ? 0 : dns->ntxts, dns->ntxts, txt, true) < 0) goto cleanup; - } - } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { if (foundIdx == dns->ntxts) { diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 3209604..7406652 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -1025,7 +1025,7 @@ virNodeDevCapPciDevIommuGroupParseXML(xmlXPathContextPtr ctxt, pciAddr->function = addr.function; if (VIR_APPEND_ELEMENT(data->pci_dev.iommuGroupDevices, data->pci_dev.nIommuGroupDevices, - pciAddr) < 0) { + pciAddr, false) < 0) { virReportOOMError(); goto cleanup; } diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c index 8dc2592..39420b6 100644 --- a/src/esx/esx_vi.c +++ b/src/esx/esx_vi.c @@ -1750,7 +1750,7 @@ esxVI_Alloc(void **ptrptr, size_t size) return -1; } - if (virAllocN(ptrptr, size, 1) < 0) { + if (virAllocN(ptrptr, size, 1, false, 0, NULL, NULL, 0) < 0) { virReportOOMError(); return -1; } diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 990decb..01e35c4 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -1003,8 +1003,8 @@ virLXCProcessEnsureRootFS(virDomainObjPtr vm) if (VIR_INSERT_ELEMENT(vm->def->fss, 0, vm->def->nfss, - root) < 0) - goto no_memory; + root, true) < 0) + goto error; return 0; diff --git a/src/security/security_manager.c b/src/security/security_manager.c index f7c5c2e..f5ea73a 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -487,10 +487,8 @@ int virSecurityManagerGenLabel(virSecurityManagerPtr mgr, /* The seclabel must be added to @vm prior calling domainGenSecurityLabel * which may require seclabel to be presented already */ if (generated && - VIR_APPEND_ELEMENT(vm->seclabels, vm->nseclabels, seclabel) < 0) { - virReportOOMError(); + VIR_APPEND_ELEMENT(vm->seclabels, vm->nseclabels, seclabel, true) < 0) goto cleanup; - } if (sec_managers[i]->drv->domainGenSecurityLabel(sec_managers[i], vm) < 0) { if (VIR_DELETE_ELEMENT(vm->seclabels, diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 7802dda..8842d85 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1227,8 +1227,8 @@ virSecuritySELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk, if (!disk_seclabel) return -1; disk_seclabel->norelabel = true; - if (VIR_APPEND_ELEMENT(disk->seclabels, disk->nseclabels, disk_seclabel) < 0) { - virReportOOMError(); + if (VIR_APPEND_ELEMENT(disk->seclabels, disk->nseclabels, + disk_seclabel, true) < 0) { virSecurityDeviceLabelDefFree(disk_seclabel); return -1; } diff --git a/src/util/viralloc.c b/src/util/viralloc.c index 8d6a7e6..16afac7 100644 --- a/src/util/viralloc.c +++ b/src/util/viralloc.c @@ -25,6 +25,9 @@ #include "viralloc.h" #include "virlog.h" +#include "virerror.h" + +#define VIR_FROM_THIS VIR_FROM_NONE #if TEST_OOM static int testMallocNext = 0; @@ -105,14 +108,26 @@ void virAllocTestHook(void (*func)(int, void*) ATTRIBUTE_UNUSED, * virAlloc: * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Allocate 'size' bytes of memory. Return the address of the * allocated memory in 'ptrptr'. The newly allocated memory is - * filled with zeros. + * filled with zeros. In case of OOM error and @report is true, + * the error is reported. * * Returns -1 on failure to allocate, zero on success */ -int virAlloc(void *ptrptr, size_t size) +int virAlloc(void *ptrptr, + size_t size, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { #if TEST_OOM if (virAllocTestFail()) { @@ -122,8 +137,11 @@ int virAlloc(void *ptrptr, size_t size) #endif *(void **)ptrptr = calloc(1, size); - if (*(void **)ptrptr == NULL) + if (*(void **)ptrptr == NULL) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); return -1; + } return 0; } @@ -132,15 +150,28 @@ int virAlloc(void *ptrptr, size_t size) * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate * @count: number of elements to allocate + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Allocate an array of memory 'count' elements long, * each with 'size' bytes. Return the address of the * allocated memory in 'ptrptr'. The newly allocated - * memory is filled with zeros. + * memory is filled with zeros. In case of OOM error + * and @report is true, the error is reported. * * Returns -1 on failure to allocate, zero on success */ -int virAllocN(void *ptrptr, size_t size, size_t count) +int virAllocN(void *ptrptr, + size_t size, + size_t count, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { #if TEST_OOM if (virAllocTestFail()) { @@ -150,8 +181,11 @@ int virAllocN(void *ptrptr, size_t size, size_t count) #endif *(void**)ptrptr = calloc(count, size); - if (*(void**)ptrptr == NULL) + if (*(void**)ptrptr == NULL) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); return -1; + } return 0; } @@ -160,16 +194,29 @@ int virAllocN(void *ptrptr, size_t size, size_t count) * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate * @count: number of elements in array + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Resize the block of memory in 'ptrptr' to be an array of * 'count' elements, each 'size' bytes in length. Update 'ptrptr' * with the address of the newly allocated memory. On failure, * 'ptrptr' is not changed and still points to the original memory * block. Any newly allocated memory in 'ptrptr' is uninitialized. + * In case of OOM error and @report is true, the error is reported. * * Returns -1 on failure to allocate, zero on success */ -int virReallocN(void *ptrptr, size_t size, size_t count) +int virReallocN(void *ptrptr, + size_t size, + size_t count, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { void *tmp; #if TEST_OOM @@ -178,12 +225,17 @@ int virReallocN(void *ptrptr, size_t size, size_t count) #endif if (xalloc_oversized(count, size)) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); errno = ENOMEM; return -1; } tmp = realloc(*(void**)ptrptr, size * count); - if (!tmp && (size * count)) + if (!tmp && (size * count)) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); return -1; + } *(void**)ptrptr = tmp; return 0; } @@ -194,24 +246,41 @@ int virReallocN(void *ptrptr, size_t size, size_t count) * @size: number of bytes per element * @countptr: pointer to number of elements in array * @add: number of elements to add + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Resize the block of memory in 'ptrptr' to be an array of * '*countptr' + 'add' elements, each 'size' bytes in length. * Update 'ptrptr' and 'countptr' with the details of the newly * allocated memory. On failure, 'ptrptr' and 'countptr' are not * changed. Any newly allocated memory in 'ptrptr' is zero-filled. + * In case of OOM error and @report is true, the error is reported. * * Returns -1 on failure to allocate, zero on success */ -int virExpandN(void *ptrptr, size_t size, size_t *countptr, size_t add) +int virExpandN(void *ptrptr, + size_t size, + size_t *countptr, + size_t add, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { int ret; if (*countptr + add < *countptr) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); errno = ENOMEM; return -1; } - ret = virReallocN(ptrptr, size, *countptr + add); + ret = virReallocN(ptrptr, size, *countptr + add, report, + domcode, filename, funcname, linenr); if (ret == 0) { memset(*(char **)ptrptr + (size * *countptr), 0, size * add); *countptr += add; @@ -226,22 +295,38 @@ int virExpandN(void *ptrptr, size_t size, size_t *countptr, size_t add) * @allocptr: pointer to number of elements allocated in array * @count: number of elements currently used in array * @add: minimum number of additional elements to support in array + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * If 'count' + 'add' is larger than '*allocptr', then resize the * block of memory in 'ptrptr' to be an array of at least 'count' + * 'add' elements, each 'size' bytes in length. Update 'ptrptr' and * 'allocptr' with the details of the newly allocated memory. On * failure, 'ptrptr' and 'allocptr' are not changed. Any newly - * allocated memory in 'ptrptr' is zero-filled. + * allocated memory in 'ptrptr' is zero-filled. In case of OOM error + * and @report is true, the error is reported. * * Returns -1 on failure to allocate, zero on success */ -int virResizeN(void *ptrptr, size_t size, size_t *allocptr, size_t count, - size_t add) +int virResizeN(void *ptrptr, + size_t size, + size_t *allocptr, + size_t count, + size_t add, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { size_t delta; if (count + add < count) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); errno = ENOMEM; return -1; } @@ -251,7 +336,8 @@ int virResizeN(void *ptrptr, size_t size, size_t *allocptr, size_t count, delta = count + add - *allocptr; if (delta < *allocptr / 2) delta = *allocptr / 2; - return virExpandN(ptrptr, size, allocptr, delta); + return virExpandN(ptrptr, size, allocptr, delta, report, + domcode, filename, funcname, linenr); } /** @@ -270,7 +356,8 @@ int virResizeN(void *ptrptr, size_t size, size_t *allocptr, size_t count, void virShrinkN(void *ptrptr, size_t size, size_t *countptr, size_t toremove) { if (toremove < *countptr) - ignore_value(virReallocN(ptrptr, size, *countptr -= toremove)); + ignore_value(virReallocN(ptrptr, size, *countptr -= toremove, + false, 0, NULL, NULL, 0)); else { virFree(ptrptr); *countptr = 0; @@ -293,6 +380,11 @@ void virShrinkN(void *ptrptr, size_t size, size_t *countptr, size_t toremove) * @inPlace: false if we should expand the allocated memory before * moving, true if we should assume someone else *has * already* done that. + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Re-allocate an array of *countptr elements, each sizeof(*ptrptr) bytes * long, to be *countptr+add elements long, then appropriately move @@ -301,7 +393,8 @@ void virShrinkN(void *ptrptr, size_t size, size_t *countptr, size_t toremove) * allocated memory in *ptrptr and the new size in *countptr. If * newelems is NULL, the new elements at ptrptr[at] are instead filled * with zero. at must be between [0,*countptr], except that -1 is - * treated the same as *countptr for convenience. + * treated the same as *countptr for convenience. In case of OOM error + * and @report is true, the error is reported. * * Returns -1 on failure, 0 on success */ @@ -309,19 +402,26 @@ int virInsertElementsN(void *ptrptr, size_t size, size_t at, size_t *countptr, size_t add, void *newelems, - bool clearOriginal, bool inPlace) + bool clearOriginal, bool inPlace, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { if (at == -1) { at = *countptr; } else if (at > *countptr) { - VIR_WARN("out of bounds index - count %zu at %zu add %zu", - *countptr, at, add); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("out of bounds index - count %zu at %zu add %zu"), + *countptr, at, add); return -1; } if (inPlace) { *countptr += add; - } else if (virExpandN(ptrptr, size, countptr, add) < 0) { + } else if (virExpandN(ptrptr, size, countptr, add, report, + domcode, filename, funcname, linenr) < 0) { return -1; } @@ -397,6 +497,11 @@ virDeleteElementsN(void *ptrptr, size_t size, size_t at, * @struct_size: size of initial struct * @element_size: size of array elements * @count: number of array elements to allocate + * @report: whether to report OOM error, if there is one + * @domcode: error domain code + * @filename: caller's filename + * @funcname: caller's funcname + * @linenr: caller's line number * * Allocate struct_size bytes plus an array of 'count' elements, each * of size element_size. This sort of allocation is useful for @@ -405,11 +510,20 @@ virDeleteElementsN(void *ptrptr, size_t size, size_t at, * The caller of this type of API is expected to know the length of * the array that will be returned and allocate a suitable buffer to * contain the returned data. C99 refers to these variable length - * objects as structs containing flexible array members. + * objects as structs containing flexible array members. In case of + * OOM error and @report is true, the error is reported. * * Returns -1 on failure, 0 on success */ -int virAllocVar(void *ptrptr, size_t struct_size, size_t element_size, size_t count) +int virAllocVar(void *ptrptr, + size_t struct_size, + size_t element_size, + size_t count, + bool report, + int domcode, + const char *filename, + const char *funcname, + size_t linenr) { size_t alloc_size = 0; @@ -419,14 +533,19 @@ int virAllocVar(void *ptrptr, size_t struct_size, size_t element_size, size_t co #endif if (VIR_ALLOC_VAR_OVERSIZED(struct_size, count, element_size)) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); errno = ENOMEM; return -1; } alloc_size = struct_size + (element_size * count); *(void **)ptrptr = calloc(1, alloc_size); - if (*(void **)ptrptr == NULL) + if (*(void **)ptrptr == NULL) { + if (report) + virReportOOMErrorFull(domcode, filename, funcname, linenr); return -1; + } return 0; } diff --git a/src/util/viralloc.h b/src/util/viralloc.h index 35d3a37..f0dba49 100644 --- a/src/util/viralloc.h +++ b/src/util/viralloc.h @@ -46,30 +46,36 @@ /* Don't call these directly - use the macros below */ -int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK - ATTRIBUTE_NONNULL(1); -int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK - ATTRIBUTE_NONNULL(1); -int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK - ATTRIBUTE_NONNULL(1); -int virExpandN(void *ptrptr, size_t size, size_t *count, size_t add) +int virAlloc(void *ptrptr, size_t size, bool report, int domcode, + const char *filename, const char *funcname, size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +int virAllocN(void *ptrptr, size_t size, size_t count, bool report, int domcode, + const char *filename, const char *funcname, size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +int virReallocN(void *ptrptr, size_t size, size_t count, bool report, int domcode, + const char *filename, const char *funcname, size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +int virExpandN(void *ptrptr, size_t size, size_t *count, size_t add, bool report, + int domcode, const char *filename, const char *funcname, size_t linenr) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); -int virResizeN(void *ptrptr, size_t size, size_t *alloc, size_t count, - size_t desired) +int virResizeN(void *ptrptr, size_t size, size_t *alloc, size_t count, size_t desired, + bool report, int domcode, const char *filename, + const char *funcname, size_t linenr) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); void virShrinkN(void *ptrptr, size_t size, size_t *count, size_t toremove) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); int virInsertElementsN(void *ptrptr, size_t size, size_t at, size_t *countptr, size_t add, void *newelem, - bool clearOriginal, bool inPlace) + bool clearOriginal, bool inPlace, bool report, int domcode, + const char *filename, const char *funcname, size_t linenr) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); int virDeleteElementsN(void *ptrptr, size_t size, size_t at, size_t *countptr, size_t toremove, bool inPlace) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); -int virAllocVar(void *ptrptr, - size_t struct_size, - size_t element_size, - size_t count) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); +int virAllocVar(void *ptrptr, size_t struct_size, size_t element_size, size_t count, + bool report, int domcode, const char *filename, + const char *funcname, size_t linenr) + ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); /** @@ -82,9 +88,24 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * + * Returns -1 on failure (with OOM error reported), 0 on success + */ +# define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr)), true, VIR_FROM_THIS, \ + __FILE__, __FUNCTION__, __LINE__) + +/** + * VIR_ALLOC_QUIET: + * @ptr: pointer to hold address of allocated memory + * + * Allocate sizeof(*ptr) bytes of memory and store + * the address of allocated memory in 'ptr'. Fill the + * newly allocated memory with zeros. + * + * This macro is safe to use on arguments with side effects. + * * Returns -1 on failure, 0 on success */ -# define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr))) +# define VIR_ALLOC_QUIET(ptr) virAlloc(&(ptr), sizeof(*(ptr)), false, 0, NULL, NULL, 0) /** * VIR_ALLOC_N: @@ -97,9 +118,26 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * + * Returns -1 on failure (with OOM error reported), 0 on success + */ +# define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count), true, \ + VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) + +/** + * VIR_ALLOC_N_QUIET: + * @ptr: pointer to hold address of allocated memory + * @count: number of elements to allocate + * + * Allocate an array of 'count' elements, each sizeof(*ptr) + * bytes long and store the address of allocated memory in + * 'ptr'. Fill the newly allocated memory with zeros. + * + * This macro is safe to use on arguments with side effects. + * * Returns -1 on failure, 0 on success */ -# define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count)) +# define VIR_ALLOC_N_QUIET(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count), \ + false, 0, NULL, NULL, 0) /** * VIR_REALLOC_N: @@ -112,9 +150,27 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * + * Returns -1 on failure (with OOM error reported), 0 on success + */ +# define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count), \ + true, VIR_FROM_THIS, __FILE__, \ + __FUNCTION__, __LINE__) + +/** + * VIR_REALLOC_N_QUIET: + * @ptr: pointer to hold address of allocated memory + * @count: number of elements to allocate + * + * Re-allocate an array of 'count' elements, each sizeof(*ptr) + * bytes long and store the address of allocated memory in + * 'ptr'. If 'ptr' grew, the added memory is uninitialized. + * + * This macro is safe to use on arguments with side effects. + * * Returns -1 on failure, 0 on success */ -# define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count)) +# define VIR_REALLOC_N_QUIET(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count), \ + false, 0, NULL, NULL, 0) /** * VIR_EXPAND_N: @@ -129,10 +185,29 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * - * Returns -1 on failure, 0 on success + * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_EXPAND_N(ptr, count, add) \ - virExpandN(&(ptr), sizeof(*(ptr)), &(count), add) + virExpandN(&(ptr), sizeof(*(ptr)), &(count), add, true, VIR_FROM_THIS, \ + __FILE__, __FUNCTION__, __LINE__) + +/** + * VIR_EXPAND_N_QUIET: + * @ptr: pointer to hold address of allocated memory + * @count: variable tracking number of elements currently allocated + * @add: number of elements to add + * + * Re-allocate an array of 'count' elements, each sizeof(*ptr) + * bytes long, to be 'count' + 'add' elements long, then store the + * address of allocated memory in 'ptr' and the new size in 'count'. + * The new elements are filled with zero. + * + * This macro is safe to use on arguments with side effects. + * + * Returns -1 on failure, 0 on success + */ +# define VIR_EXPAND_N_QUIET(ptr, count, add) \ + virExpandN(&(ptr), sizeof(*(ptr)), &(count), add, false, 0, NULL, NULL, 0) /** * VIR_RESIZE_N: @@ -154,10 +229,37 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * - * Returns -1 on failure, 0 on success + * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_RESIZE_N(ptr, alloc, count, add) \ - virResizeN(&(ptr), sizeof(*(ptr)), &(alloc), count, add) + virResizeN(&(ptr), sizeof(*(ptr)), &(alloc), count, add, true, \ + VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) + +/** + * VIR_RESIZE_N_QUIET: + * @ptr: pointer to hold address of allocated memory + * @alloc: variable tracking number of elements currently allocated + * @count: number of elements currently in use + * @add: minimum number of elements to additionally support + * + * Blindly using VIR_EXPAND_N(array, alloc, 1) in a loop scales + * quadratically, because every iteration must copy contents from + * all prior iterations. But amortized linear scaling can be achieved + * by tracking allocation size separately from the number of used + * elements, and growing geometrically only as needed. + * + * If 'count' + 'add' is larger than 'alloc', then geometrically reallocate + * the array of 'alloc' elements, each sizeof(*ptr) bytes long, and store + * the address of allocated memory in 'ptr' and the new size in 'alloc'. + * The new elements are filled with zero. + * + * This macro is safe to use on arguments with side effects. + * + * Returns -1 on failure, 0 on success + */ +# define VIR_RESIZE_N_QUIET(ptr, alloc, count, add) \ + virResizeN(&(ptr), sizeof(*(ptr)), &(alloc), count, add, \ + false, 0, NULL, NULL, 0) /** * VIR_SHRINK_N: @@ -224,6 +326,7 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * @newelem: the new element to move into place (*not* a pointer to * the element, but the element itself). * (the original will be zeroed out if successful) + * @report: whether report OOM error on failure * * Re-allocate an array of 'count' elements, each sizeof(*ptr) bytes * long, to be 'count' + 1 elements long, then appropriately move @@ -252,18 +355,22 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * Returns -1 on failure, 0 on success */ -# define VIR_INSERT_ELEMENT(ptr, at, count, newelem) \ +# define VIR_INSERT_ELEMENT(ptr, at, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), at, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, false) -# define VIR_INSERT_ELEMENT_COPY(ptr, at, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, false, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_INSERT_ELEMENT_COPY(ptr, at, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), at, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, false) -# define VIR_INSERT_ELEMENT_INPLACE(ptr, at, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, false, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_INSERT_ELEMENT_INPLACE(ptr, at, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), at, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, true) -# define VIR_INSERT_ELEMENT_COPY_INPLACE(ptr, at, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, true, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_INSERT_ELEMENT_COPY_INPLACE(ptr, at, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), at, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, true) + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, true, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) /** * VIR_APPEND_ELEMENT: @@ -272,6 +379,7 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * @newelem: the new element to move into place (*not* a pointer to * the element, but the element itself). * (the original will be zeroed out if successful) + * @report: whether report OOM error on failure * * Re-allocate an array of 'count' elements, each sizeof(*ptr) bytes * long, to be 'count' + 1 elements long, then copy the item from @@ -300,18 +408,22 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * Returns -1 on failure, 0 on success */ -# define VIR_APPEND_ELEMENT(ptr, count, newelem) \ +# define VIR_APPEND_ELEMENT(ptr, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), -1, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, false) -# define VIR_APPEND_ELEMENT_COPY(ptr, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, false, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_APPEND_ELEMENT_COPY(ptr, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), -1, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, false) -# define VIR_APPEND_ELEMENT_INPLACE(ptr, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, false, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_APPEND_ELEMENT_INPLACE(ptr, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), -1, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, true) -# define VIR_APPEND_ELEMENT_COPY_INPLACE(ptr, count, newelem) \ + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), true, true, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) +# define VIR_APPEND_ELEMENT_COPY_INPLACE(ptr, count, newelem, report) \ virInsertElementsN(&(ptr), sizeof(*(ptr)), -1, &(count), \ - VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, true) + VIR_TYPEMATCH(ptr, &(newelem)), &(newelem), false, true, \ + report, VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) /** * VIR_DELETE_ELEMENT: @@ -365,10 +477,33 @@ void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); * * This macro is safe to use on arguments with side effects. * - * Returns -1 on failure, 0 on success + * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_ALLOC_VAR(ptr, type, count) \ - virAllocVar(&(ptr), sizeof(*(ptr)), sizeof(type), (count)) + virAllocVar(&(ptr), sizeof(*(ptr)), sizeof(type), (count), true, \ + VIR_FROM_THIS, __FILE__, __FUNCTION__, __LINE__) + +/** + * VIR_ALLOC_VAR_QUIET: + * @ptr: pointer to hold address of allocated memory + * @type: element type of trailing array + * @count: number of array elements to allocate + * + * Allocate sizeof(*ptr) bytes plus an array of 'count' elements, each + * sizeof('type'). This sort of allocation is useful for receiving + * the data of certain ioctls and other APIs which return a struct in + * which the last element is an array of undefined length. The caller + * of this type of API is expected to know the length of the array + * that will be returned and allocate a suitable buffer to contain the + * returned data. C99 refers to these variable length objects as + * structs containing flexible array members. + * + * This macro is safe to use on arguments with side effects. + * + * Returns -1 on failure, 0 on success + */ +# define VIR_ALLOC_VAR_QUIET(ptr, type, count) \ + virAllocVar(&(ptr), sizeof(*(ptr)), sizeof(type), (count), false, 0, NULL, NULL, 0) /** * VIR_FREE: diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c index 4969497..ee0be6c 100644 --- a/src/util/virbuffer.c +++ b/src/util/virbuffer.c @@ -126,7 +126,7 @@ virBufferGrow(virBufferPtr buf, unsigned int len) size = buf->use + len + 1000; - if (VIR_REALLOC_N(buf->content, size) < 0) { + if (VIR_REALLOC_N_QUIET(buf->content, size) < 0) { virBufferSetError(buf, errno); return -1; } @@ -382,7 +382,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str) } if (xalloc_oversized(6, len) || - VIR_ALLOC_N(escaped, 6 * len + 1) < 0) { + VIR_ALLOC_N_QUIET(escaped, 6 * len + 1) < 0) { virBufferSetError(buf, errno); return; } @@ -499,7 +499,7 @@ virBufferEscape(virBufferPtr buf, char escape, const char *toescape, } if (xalloc_oversized(2, len) || - VIR_ALLOC_N(escaped, 2 * len + 1) < 0) { + VIR_ALLOC_N_QUIET(escaped, 2 * len + 1) < 0) { virBufferSetError(buf, errno); return; } @@ -597,7 +597,7 @@ virBufferEscapeShell(virBufferPtr buf, const char *str) if (*str) { len = strlen(str); if (xalloc_oversized(4, len) || - VIR_ALLOC_N(escaped, 4 * len + 3) < 0) { + VIR_ALLOC_N_QUIET(escaped, 4 * len + 3) < 0) { virBufferSetError(buf, errno); return; } diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index e0b25ed..13fd162 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -1171,7 +1171,7 @@ static int virCgroupPartitionEscape(char **path) if ((rc = virCgroupPartitionNeedsEscaping(*path)) <= 0) return rc; - if (VIR_INSERT_ELEMENT(*path, 0, len, escape) < 0) + if (VIR_INSERT_ELEMENT(*path, 0, len, escape, false) < 0) return -ENOMEM; return 0; diff --git a/src/util/virerror.c b/src/util/virerror.c index 4789bae..e238dce 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -209,7 +209,7 @@ virLastErrorObject(void) virErrorPtr err; err = virThreadLocalGet(&virLastErr); if (!err) { - if (VIR_ALLOC(err) < 0) + if (VIR_ALLOC_QUIET(err) < 0) return NULL; if (virThreadLocalSet(&virLastErr, err) < 0) VIR_FREE(err); @@ -330,7 +330,7 @@ virSaveLastError(void) virErrorPtr to; int saved_errno = errno; - if (VIR_ALLOC(to) < 0) + if (VIR_ALLOC_QUIET(to) < 0) return NULL; virCopyLastError(to); diff --git a/src/util/virpci.c b/src/util/virpci.c index 54f7715..9ed257e 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -2009,7 +2009,7 @@ virPCIGetIOMMUGroupAddressesAddOne(virPCIDeviceAddressPtr newDevAddr, void *opaq *copyAddr = *newDevAddr; if (VIR_APPEND_ELEMENT(*addrList->iommuGroupDevices, - *addrList->nIommuGroupDevices, copyAddr) < 0) { + *addrList->nIommuGroupDevices, copyAddr, false) < 0) { virReportOOMError(); goto cleanup; } diff --git a/src/util/virthreadpthread.c b/src/util/virthreadpthread.c index 75b5fd6..ca841e4 100644 --- a/src/util/virthreadpthread.c +++ b/src/util/virthreadpthread.c @@ -174,7 +174,7 @@ int virThreadCreate(virThreadPtr thread, if ((err = pthread_attr_init(&attr)) != 0) goto cleanup; - if (VIR_ALLOC(args) < 0) { + if (VIR_ALLOC_QUIET(args) < 0) { err = ENOMEM; goto cleanup; } diff --git a/tests/commandhelper.c b/tests/commandhelper.c index e4cc5d2..d492c70 100644 --- a/tests/commandhelper.c +++ b/tests/commandhelper.c @@ -35,6 +35,7 @@ #ifndef WIN32 +# define VIR_FROM_THIS VIR_FROM_NONE static int envsort(const void *a, const void *b) { const char *const*astrptr = a; diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c index 520feba..b234b30 100644 --- a/tests/networkxml2conftest.c +++ b/tests/networkxml2conftest.c @@ -16,6 +16,8 @@ #include "network/bridge_driver.h" #include "virstring.h" +#define VIR_FROM_THIS VIR_FROM_NONE + static int testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr caps) { diff --git a/tests/test_conf.c b/tests/test_conf.c index d5467e8..acf41c6 100644 --- a/tests/test_conf.c +++ b/tests/test_conf.c @@ -20,7 +20,7 @@ int main(int argc, char **argv) goto cleanup; } - if (VIR_ALLOC_N(buffer, len) < 0) { + if (VIR_ALLOC_N_QUIET(buffer, len) < 0) { fprintf(stderr, "out of memory\n"); goto cleanup; } diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 8e0c59e..73e4a2d 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -37,6 +37,8 @@ #include "viralloc.h" #include "virstring.h" +#define VIR_FROM_THIS VIR_FROM_NONE + static virCapsPtr caps; static virDomainXMLOptionPtr xmlopt; -- 1.8.1.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list