aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-08-02 17:21:50 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-08-02 17:21:50 +0100
commit7f1cab9c628a798ae2607940993771e6300e9e00 (patch)
treeb88609bc5a24f5b1c771367ce459c64bce4bcb27
parent526f1f3a5c6726e3d3b893d8063d31fda091c7e0 (diff)
parente17bdaab2b36db54f0214a14f394fa773cee58df (diff)
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>
-rw-r--r--scripts/coverity-scan/model.c227
-rw-r--r--softmmu/vl.c47
2 files changed, 139 insertions, 135 deletions
diff --git a/scripts/coverity-scan/model.c b/scripts/coverity-scan/model.c
index 2c0346ff25..9d4fba53d9 100644
--- a/scripts/coverity-scan/model.c
+++ b/scripts/coverity-scan/model.c
@@ -45,9 +45,10 @@ typedef struct va_list_str *va_list;
/* exec.c */
typedef struct AddressSpace AddressSpace;
+typedef struct MemoryRegionCache MemoryRegionCache;
typedef uint64_t hwaddr;
typedef uint32_t MemTxResult;
-typedef uint64_t MemTxAttrs;
+typedef struct MemTxAttrs {} MemTxAttrs;
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];
}
+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,
MemTxAttrs attrs,
- uint8_t *buf, int len)
+ void *buf, int len)
{
MemTxResult result;
// 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,
MemTxAttrs attrs,
- const uint8_t *buf, int len)
+ const void *buf, int len)
{
MemTxResult result;
__bufread(buf, len);
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 */
@@ -136,54 +178,56 @@ uint8_t replay_get_byte(void)
void *g_malloc_n(size_t nmemb, size_t size)
{
- size_t sz;
void *ptr;
__coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size);
- sz = nmemb * size;
- ptr = __coverity_alloc__(sz);
+ ptr = __coverity_alloc__(nmemb * size);
+ if (!ptr) {
+ __coverity_panic__();
+ }
__coverity_mark_as_uninitialized_buffer__(ptr);
- __coverity_mark_as_afm_allocated__(ptr, "g_free");
+ __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
}
void *g_malloc0_n(size_t nmemb, size_t size)
{
- size_t sz;
void *ptr;
__coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size);
- sz = nmemb * size;
- ptr = __coverity_alloc__(sz);
+ ptr = __coverity_alloc__(nmemb * size);
+ if (!ptr) {
+ __coverity_panic__();
+ }
__coverity_writeall0__(ptr);
- __coverity_mark_as_afm_allocated__(ptr, "g_free");
+ __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
}
void *g_realloc_n(void *ptr, size_t nmemb, size_t size)
{
- size_t sz;
-
__coverity_negative_sink__(nmemb);
__coverity_negative_sink__(size);
- sz = nmemb * size;
__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
* model that. See Coverity's realloc() model
*/
__coverity_writeall__(ptr);
- __coverity_mark_as_afm_allocated__(ptr, "g_free");
+ __coverity_mark_as_afm_allocated__(ptr, AFM_free);
return ptr;
}
void g_free(void *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);
}
-/* 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)
{
- 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)
{
- 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)
{
- 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)
{
- return g_try_malloc_n(1, size);
-}
-
-void *g_try_malloc0(size_t size)
-{
- return g_try_malloc0_n(1, size);
-}
-
-void *g_try_realloc(void *ptr, size_t size)
-{
- return g_try_realloc_n(ptr, 1, size);
-}
-
-/* Other memory allocation functions */
-
-void *g_memdup(const void *ptr, unsigned size)
-{
- unsigned char *dup;
- unsigned i;
+ int nomem;
- if (!ptr) {
+ if (nomem) {
return NULL;
}
-
- dup = g_malloc(size);
- for (i = 0; i < size; i++)
- dup[i] = ((unsigned char *)ptr)[i];
- return dup;
+ return g_malloc(size);
}
-/*
- * GLib string allocation functions
- */
-
-char *g_strdup(const char *s)
+void *g_try_malloc0(size_t size)
{
- char *dup;
- size_t i;
+ int nomem;
- if (!s) {
+ if (nomem) {
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;
+ return g_malloc0(size);
}
-char *g_strndup(const char *s, size_t n)
+void *g_try_realloc(void *ptr, size_t size)
{
- char *dup;
- size_t i;
-
- __coverity_negative_sink__(n);
+ int nomem;
- if (!s) {
+ if (nomem) {
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;
+ return g_realloc(ptr, size);
}
/* Other glib functions */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 4dee472c79..5ca11e7469 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -31,6 +31,7 @@
#include "qapi/compat-policy.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qjson.h"
#include "qemu-version.h"
#include "qemu/cutils.h"
@@ -1535,22 +1536,35 @@ 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
machine_parse_property_opt(QemuOptsList *opts_list, const char *propname,
const char *arg, Error **errp)
{
- QDict *opts, *prop;
+ QDict *prop = NULL;
bool help = false;
- ERRP_GUARD();
prop = keyval_parse(arg, opts_list->implied_opt_name, &help, errp);
if (help) {
qemu_opts_print_help(opts_list, true);
exit(0);
}
- opts = qdict_new();
- qdict_put(opts, propname, prop);
- keyval_merge(machine_opts_dict, opts, errp);
- qobject_unref(opts);
+ if (!prop) {
+ return;
+ }
+ machine_merge_property(propname, prop, errp);
+ qobject_unref(prop);
}
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)
{
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 true;
@@ -2173,6 +2188,8 @@ static void qemu_record_config_group(const char *group, QDict *dict,
*/
assert(!from_json);
keyval_merge(machine_opts_dict, dict, errp);
+ } else if (g_str_equal(group, "smp-opts")) {
+ machine_merge_property("smp", dict, &error_fatal);
} else {
abort();
}
@@ -2439,13 +2456,15 @@ static void qemu_validate_options(const QDict *machine_opts)
static void qemu_process_sugar_options(void)
{
if (mem_prealloc) {
- char *val;
-
- val = g_strdup_printf("%d",
- (uint32_t) qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1));
- object_register_sugar_prop("memory-backend", "prealloc-threads", val,
- false);
- g_free(val);
+ QObject *smp = qdict_get(machine_opts_dict, "smp");
+ if (smp && qobject_type(smp) == QTYPE_QDICT) {
+ QObject *cpus = qdict_get(qobject_to(QDict, smp), "cpus");
+ if (cpus && qobject_type(cpus) == QTYPE_QSTRING) {
+ const char *val = qstring_get_str(qobject_to(QString, cpus));
+ object_register_sugar_prop("memory-backend", "prealloc-threads",
+ val, false);
+ }
+ }
object_register_sugar_prop("memory-backend", "prealloc", "on", false);
}