Fix for smp-opts in configuration file.

Update Coverity model to what's currently uploaded.
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmEHw7EUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroPIHwf+OOr857Wkn70dckPGG5MOejR+eATn
 WXdkb6J9mo953fhiEH3/7tgyAEwh3qHHxCKwJQdY5beTXu2h5fC2WyNadqTBi2ol
 PnT9T05beFAqyq0SsmMH/0hHNVOO/rPp2FjFce7+8FinW+oqvI9NVkJtjiBdReQw
 K8ychTJet0UxvQgL755ujT3CcB7q4W3fbPg/a86K14hQndRsjyHiqYb96oNOnHgo
 vkfI1kA0ljX2A59+nkUzQZwZ00P/6bpk/tXVgLcHWQQHUS+QLMHu+HdvdySeK5mt
 7fjEZnELF640YnIHtF8QKgXf1MS0wE4VGL9AmHjCV1zsm7JPiI8sdp2AzQ==
 =ScAY
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging

Fix for smp-opts in configuration file.
Update Coverity model to what's currently uploaded.

# gpg: Signature made Mon 02 Aug 2021 11:06:41 BST
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini-gitlab/tags/for-upstream:
  coverity-model: write models fully for non-array allocation functions
  coverity-model: constrain g_malloc/g_malloc0/g_realloc as never returning NULL
  coverity-model: clean up the models for array allocation functions
  coverity-model: remove model for more allocation functions
  coverity-model: make g_free a synonym of free
  coverity-model: update address_space_read/write models
  vl: stop recording -smp in QemuOpts
  vl: introduce machine_merge_property

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-08-02 17:21:50 +01:00
commit 7f1cab9c62
2 changed files with 143 additions and 139 deletions

View File

@ -45,9 +45,10 @@ typedef struct va_list_str *va_list;
/* exec.c */ /* exec.c */
typedef struct AddressSpace AddressSpace; typedef struct AddressSpace AddressSpace;
typedef struct MemoryRegionCache MemoryRegionCache;
typedef uint64_t hwaddr; typedef uint64_t hwaddr;
typedef uint32_t MemTxResult; typedef uint32_t MemTxResult;
typedef uint64_t MemTxAttrs; typedef struct MemTxAttrs {} MemTxAttrs;
static void __bufwrite(uint8_t *buf, ssize_t len) static void __bufwrite(uint8_t *buf, ssize_t len)
{ {
@ -67,9 +68,40 @@ static void __bufread(uint8_t *buf, ssize_t len)
int last = buf[len-1]; int last = buf[len-1];
} }
MemTxResult address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
MemTxAttrs attrs,
void *buf, int len)
{
MemTxResult result;
// TODO: investigate impact of treating reads as producing
// tainted data, with __coverity_tainted_data_argument__(buf).
__bufwrite(buf, len);
return result;
}
MemTxResult address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
MemTxAttrs attrs,
const void *buf, int len)
{
MemTxResult result;
__bufread(buf, len);
return result;
}
MemTxResult address_space_rw_cached(MemoryRegionCache *cache, hwaddr addr,
MemTxAttrs attrs,
void *buf, int len, bool is_write)
{
if (is_write) {
return address_space_write_cached(cache, addr, attrs, buf, len);
} else {
return address_space_read_cached(cache, addr, attrs, buf, len);
}
}
MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxAttrs attrs,
uint8_t *buf, int len) void *buf, int len)
{ {
MemTxResult result; MemTxResult result;
// TODO: investigate impact of treating reads as producing // TODO: investigate impact of treating reads as producing
@ -80,13 +112,23 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,
MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxAttrs attrs,
const uint8_t *buf, int len) const void *buf, int len)
{ {
MemTxResult result; MemTxResult result;
__bufread(buf, len); __bufread(buf, len);
return result; return result;
} }
MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs,
void *buf, int len, bool is_write)
{
if (is_write) {
return address_space_write(as, addr, attrs, buf, len);
} else {
return address_space_read(as, addr, attrs, buf, len);
}
}
/* Tainting */ /* Tainting */
@ -136,54 +178,56 @@ uint8_t replay_get_byte(void)
void *g_malloc_n(size_t nmemb, size_t size) void *g_malloc_n(size_t nmemb, size_t size)
{ {
size_t sz;
void *ptr; void *ptr;
__coverity_negative_sink__(nmemb); __coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size); __coverity_negative_sink__(size);
sz = nmemb * size; ptr = __coverity_alloc__(nmemb * size);
ptr = __coverity_alloc__(sz); if (!ptr) {
__coverity_panic__();
}
__coverity_mark_as_uninitialized_buffer__(ptr); __coverity_mark_as_uninitialized_buffer__(ptr);
__coverity_mark_as_afm_allocated__(ptr, "g_free"); __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr; return ptr;
} }
void *g_malloc0_n(size_t nmemb, size_t size) void *g_malloc0_n(size_t nmemb, size_t size)
{ {
size_t sz;
void *ptr; void *ptr;
__coverity_negative_sink__(nmemb); __coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size); __coverity_negative_sink__(size);
sz = nmemb * size; ptr = __coverity_alloc__(nmemb * size);
ptr = __coverity_alloc__(sz); if (!ptr) {
__coverity_panic__();
}
__coverity_writeall0__(ptr); __coverity_writeall0__(ptr);
__coverity_mark_as_afm_allocated__(ptr, "g_free"); __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr; return ptr;
} }
void *g_realloc_n(void *ptr, size_t nmemb, size_t size) void *g_realloc_n(void *ptr, size_t nmemb, size_t size)
{ {
size_t sz;
__coverity_negative_sink__(nmemb); __coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size); __coverity_negative_sink__(size);
sz = nmemb * size;
__coverity_escape__(ptr); __coverity_escape__(ptr);
ptr = __coverity_alloc__(sz); ptr = __coverity_alloc__(nmemb * size);
if (!ptr) {
__coverity_panic__();
}
/* /*
* Memory beyond the old size isn't actually initialized. Can't * Memory beyond the old size isn't actually initialized. Can't
* model that. See Coverity's realloc() model * model that. See Coverity's realloc() model
*/ */
__coverity_writeall__(ptr); __coverity_writeall__(ptr);
__coverity_mark_as_afm_allocated__(ptr, "g_free"); __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr; return ptr;
} }
void g_free(void *ptr) void g_free(void *ptr)
{ {
__coverity_free__(ptr); __coverity_free__(ptr);
__coverity_mark_as_afm_freed__(ptr, "g_free"); __coverity_mark_as_afm_freed__(ptr, AFM_free);
} }
/* /*
@ -221,140 +265,81 @@ void *g_try_realloc_n(void *ptr, size_t nmemb, size_t size)
return g_realloc_n(ptr, nmemb, size); return g_realloc_n(ptr, nmemb, size);
} }
/* Trivially derive the g_FOO() from the g_FOO_n() */ /* Derive the g_FOO() from the g_FOO_n() */
void *g_malloc(size_t size) void *g_malloc(size_t size)
{ {
return g_malloc_n(1, size); void *ptr;
__coverity_negative_sink__(size);
ptr = __coverity_alloc__(size);
if (!ptr) {
__coverity_panic__();
}
__coverity_mark_as_uninitialized_buffer__(ptr);
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
} }
void *g_malloc0(size_t size) void *g_malloc0(size_t size)
{ {
return g_malloc0_n(1, size); void *ptr;
__coverity_negative_sink__(size);
ptr = __coverity_alloc__(size);
if (!ptr) {
__coverity_panic__();
}
__coverity_writeall0__(ptr);
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
} }
void *g_realloc(void *ptr, size_t size) void *g_realloc(void *ptr, size_t size)
{ {
return g_realloc_n(ptr, 1, size); __coverity_negative_sink__(size);
__coverity_escape__(ptr);
ptr = __coverity_alloc__(size);
if (!ptr) {
__coverity_panic__();
}
/*
* Memory beyond the old size isn't actually initialized. Can't
* model that. See Coverity's realloc() model
*/
__coverity_writeall__(ptr);
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
} }
void *g_try_malloc(size_t size) void *g_try_malloc(size_t size)
{ {
return g_try_malloc_n(1, size); int nomem;
if (nomem) {
return NULL;
}
return g_malloc(size);
} }
void *g_try_malloc0(size_t size) void *g_try_malloc0(size_t size)
{ {
return g_try_malloc0_n(1, size); int nomem;
if (nomem) {
return NULL;
}
return g_malloc0(size);
} }
void *g_try_realloc(void *ptr, size_t size) void *g_try_realloc(void *ptr, size_t size)
{ {
return g_try_realloc_n(ptr, 1, size); int nomem;
}
/* Other memory allocation functions */ if (nomem) {
void *g_memdup(const void *ptr, unsigned size)
{
unsigned char *dup;
unsigned i;
if (!ptr) {
return NULL; return NULL;
} }
return g_realloc(ptr, size);
dup = g_malloc(size);
for (i = 0; i < size; i++)
dup[i] = ((unsigned char *)ptr)[i];
return dup;
}
/*
* GLib string allocation functions
*/
char *g_strdup(const char *s)
{
char *dup;
size_t i;
if (!s) {
return NULL;
}
__coverity_string_null_sink__(s);
__coverity_string_size_sink__(s);
dup = __coverity_alloc_nosize__();
__coverity_mark_as_afm_allocated__(dup, "g_free");
for (i = 0; (dup[i] = s[i]); i++) ;
return dup;
}
char *g_strndup(const char *s, size_t n)
{
char *dup;
size_t i;
__coverity_negative_sink__(n);
if (!s) {
return NULL;
}
dup = g_malloc(n + 1);
for (i = 0; i < n && (dup[i] = s[i]); i++) ;
dup[i] = 0;
return dup;
}
char *g_strdup_printf(const char *format, ...)
{
char ch, *s;
size_t len;
__coverity_string_null_sink__(format);
__coverity_string_size_sink__(format);
ch = *format;
s = __coverity_alloc_nosize__();
__coverity_writeall__(s);
__coverity_mark_as_afm_allocated__(s, "g_free");
return s;
}
char *g_strdup_vprintf(const char *format, va_list ap)
{
char ch, *s;
size_t len;
__coverity_string_null_sink__(format);
__coverity_string_size_sink__(format);
ch = *format;
ch = *(char *)ap;
s = __coverity_alloc_nosize__();
__coverity_writeall__(s);
__coverity_mark_as_afm_allocated__(s, "g_free");
return len;
}
char *g_strconcat(const char *s, ...)
{
char *s;
/*
* Can't model: last argument must be null, the others
* null-terminated strings
*/
s = __coverity_alloc_nosize__();
__coverity_writeall__(s);
__coverity_mark_as_afm_allocated__(s, "g_free");
return s;
} }
/* Other glib functions */ /* Other glib functions */

View File

@ -31,6 +31,7 @@
#include "qapi/compat-policy.h" #include "qapi/compat-policy.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qemu-version.h" #include "qemu-version.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
@ -1534,23 +1535,36 @@ static void machine_help_func(const QDict *qdict)
} }
} }
static void
machine_merge_property(const char *propname, QDict *prop, Error **errp)
{
QDict *opts;
opts = qdict_new();
/* Preserve the caller's reference to prop. */
qobject_ref(prop);
qdict_put(opts, propname, prop);
keyval_merge(machine_opts_dict, opts, errp);
qobject_unref(opts);
}
static void static void
machine_parse_property_opt(QemuOptsList *opts_list, const char *propname, machine_parse_property_opt(QemuOptsList *opts_list, const char *propname,
const char *arg, Error **errp) const char *arg, Error **errp)
{ {
QDict *opts, *prop; QDict *prop = NULL;
bool help = false; bool help = false;
ERRP_GUARD();
prop = keyval_parse(arg, opts_list->implied_opt_name, &help, errp); prop = keyval_parse(arg, opts_list->implied_opt_name, &help, errp);
if (help) { if (help) {
qemu_opts_print_help(opts_list, true); qemu_opts_print_help(opts_list, true);
exit(0); exit(0);
} }
opts = qdict_new(); if (!prop) {
qdict_put(opts, propname, prop); return;
keyval_merge(machine_opts_dict, opts, errp); }
qobject_unref(opts); machine_merge_property(propname, prop, errp);
qobject_unref(prop);
} }
static const char *pid_file; static const char *pid_file;
@ -2153,7 +2167,8 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
static bool is_qemuopts_group(const char *group) static bool is_qemuopts_group(const char *group)
{ {
if (g_str_equal(group, "object") || if (g_str_equal(group, "object") ||
g_str_equal(group, "machine")) { g_str_equal(group, "machine") ||
g_str_equal(group, "smp-opts")) {
return false; return false;
} }
return true; return true;
@ -2173,6 +2188,8 @@ static void qemu_record_config_group(const char *group, QDict *dict,
*/ */
assert(!from_json); assert(!from_json);
keyval_merge(machine_opts_dict, dict, errp); keyval_merge(machine_opts_dict, dict, errp);
} else if (g_str_equal(group, "smp-opts")) {
machine_merge_property("smp", dict, &error_fatal);
} else { } else {
abort(); abort();
} }
@ -2439,13 +2456,15 @@ static void qemu_validate_options(const QDict *machine_opts)
static void qemu_process_sugar_options(void) static void qemu_process_sugar_options(void)
{ {
if (mem_prealloc) { if (mem_prealloc) {
char *val; QObject *smp = qdict_get(machine_opts_dict, "smp");
if (smp && qobject_type(smp) == QTYPE_QDICT) {
val = g_strdup_printf("%d", QObject *cpus = qdict_get(qobject_to(QDict, smp), "cpus");
(uint32_t) qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1)); if (cpus && qobject_type(cpus) == QTYPE_QSTRING) {
object_register_sugar_prop("memory-backend", "prealloc-threads", val, const char *val = qstring_get_str(qobject_to(QString, cpus));
false); object_register_sugar_prop("memory-backend", "prealloc-threads",
g_free(val); val, false);
}
}
object_register_sugar_prop("memory-backend", "prealloc", "on", false); object_register_sugar_prop("memory-backend", "prealloc", "on", false);
} }