All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: armbru@redhat.com, Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH v16 02/24] qapi: Guarantee NULL obj on input visitor callback error
Date: Thu, 28 Apr 2016 15:45:10 -0600	[thread overview]
Message-ID: <1461879932-9020-3-git-send-email-eblake@redhat.com> (raw)
In-Reply-To: <1461879932-9020-1-git-send-email-eblake@redhat.com>

Our existing input visitors were not very consistent on errors
in a function taking 'TYPE **obj' (that is, start_struct(),
start_alternate(), type_str(), and type_any(). next_list() is
similar, except that since commit 08f9541, it can't fail).
While all of them set '*obj' to allocated storage on success,
it was not obvious whether '*obj' was guaranteed safe on failure,
or whether it was left uninitialized.  But a future patch wants
to guarantee that visit_type_FOO() does not leak a partially-
constructed obj back to the caller; it is easier to implement
this if we can reliably state that input visitors assign '*obj'
regardless of success or failure, and that on failure *obj is
NULL.  Add assertions to enforce consistency in the final
setting of err vs. *obj.

The opts-visitor start_struct() doesn't set an error, but it
also was doing a weird check for 0 size; all callers pass in
non-zero size if obj is non-NULL.

The testsuite has at least one spot where we no longer need
to pre-initialize a variable prior to a visit; valgrind confirms
that the test is still fine with the cleanup.

A later patch will document the design constraint implemented
here.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v16: tighten assertions, another commit message tweak
v15: enhance commit message, hoist assertions from later in series
v14: no change
v13: no change
v12: new patch
---
 qapi/qapi-visit-core.c        | 34 ++++++++++++++++++++++++++++++----
 qapi/opts-visitor.c           |  3 ++-
 qapi/qmp-input-visitor.c      |  4 ++++
 qapi/string-input-visitor.c   |  1 +
 tests/test-qmp-input-strict.c |  2 +-
 5 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 3cd7edc..7ad5ff4 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -23,7 +23,13 @@
 void visit_start_struct(Visitor *v, const char *name, void **obj,
                         size_t size, Error **errp)
 {
-    v->start_struct(v, name, obj, size, errp);
+    Error *err = NULL;
+
+    v->start_struct(v, name, obj, size, &err);
+    if (obj && v->type == VISITOR_INPUT) {
+        assert(!err != !*obj);
+    }
+    error_propagate(errp, err);
 }

 void visit_end_struct(Visitor *v, Error **errp)
@@ -51,10 +57,16 @@ void visit_start_alternate(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
                            bool promote_int, Error **errp)
 {
+    Error *err = NULL;
+
     assert(obj && size >= sizeof(GenericAlternate));
     if (v->start_alternate) {
-        v->start_alternate(v, name, obj, size, promote_int, errp);
+        v->start_alternate(v, name, obj, size, promote_int, &err);
     }
+    if (v->type == VISITOR_INPUT) {
+        assert(!err != !*obj);
+    }
+    error_propagate(errp, err);
 }

 void visit_end_alternate(Visitor *v)
@@ -188,7 +200,14 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)

 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
 {
-    v->type_str(v, name, obj, errp);
+    Error *err = NULL;
+
+    assert(obj);
+    v->type_str(v, name, obj, &err);
+    if (v->type == VISITOR_INPUT) {
+        assert(!err != !*obj);
+    }
+    error_propagate(errp, err);
 }

 void visit_type_number(Visitor *v, const char *name, double *obj,
@@ -199,7 +218,14 @@ void visit_type_number(Visitor *v, const char *name, double *obj,

 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
 {
-    v->type_any(v, name, obj, errp);
+    Error *err = NULL;
+
+    assert(obj);
+    v->type_any(v, name, obj, &err);
+    if (v->type == VISITOR_INPUT) {
+        assert(!err != !*obj);
+    }
+    error_propagate(errp, err);
 }

 static void output_type_enum(Visitor *v, const char *name, int *obj,
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 66aeaed..4cb6436 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -133,7 +133,7 @@ opts_start_struct(Visitor *v, const char *name, void **obj,
     const QemuOpt *opt;

     if (obj) {
-        *obj = g_malloc0(size > 0 ? size : 1);
+        *obj = g_malloc0(size);
     }
     if (ov->depth++ > 0) {
         return;
@@ -314,6 +314,7 @@ opts_type_str(Visitor *v, const char *name, char **obj, Error **errp)

     opt = lookup_scalar(ov, name, errp);
     if (!opt) {
+        *obj = NULL;
         return;
     }
     *obj = g_strdup(opt->str ? opt->str : "");
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 02d4233..77cce8b 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -120,6 +120,9 @@ static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
     QObject *qobj = qmp_input_get_object(qiv, name, true);
     Error *err = NULL;

+    if (obj) {
+        *obj = NULL;
+    }
     if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    "QDict");
@@ -267,6 +270,7 @@ static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
     QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));

     if (!qstr) {
+        *obj = NULL;
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    "string");
         return;
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index d604575..797973a 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -293,6 +293,7 @@ static void parse_type_str(Visitor *v, const char *name, char **obj,
     if (siv->string) {
         *obj = g_strdup(siv->string);
     } else {
+        *obj = NULL;
         error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    "string");
     }
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
index d71727e..d5f80ec 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qmp-input-strict.c
@@ -263,7 +263,7 @@ static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
 static void test_validate_fail_alternate(TestInputVisitorData *data,
                                          const void *unused)
 {
-    UserDefAlternate *tmp = NULL;
+    UserDefAlternate *tmp;
     Visitor *v;
     Error *err = NULL;

-- 
2.5.5

  parent reply	other threads:[~2016-04-28 21:45 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-28 21:45 [Qemu-devel] [PATCH v16 00/24] qapi visitor cleanups (post-introspection cleanups subset E) Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 01/24] qapi-visit: Add visitor.type classification Eric Blake
2016-04-28 21:45 ` Eric Blake [this message]
2016-04-29  8:28   ` [Qemu-devel] [PATCH v16 02/24] qapi: Guarantee NULL obj on input visitor callback error Markus Armbruster
2016-04-29 12:10     ` Eric Blake
2016-04-29 12:17       ` Eric Blake
2016-04-29 12:59         ` Markus Armbruster
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 03/24] qmp: Drop dead command->type Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 04/24] qmp-input: Clean up stack handling Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 05/24] qapi: Consolidate QMP input visitor creation Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 06/24] qapi: Use strict QMP input visitor in more places Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 07/24] qmp-input: Don't consume input when checking has_member Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 08/24] qapi-commands: Wrap argument visit in visit_start_struct Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 09/24] qom: Wrap prop " Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 10/24] qmp-input: Require struct push to visit members of top dict Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 11/24] qmp-input: Refactor when list is advanced Eric Blake
2016-04-29  8:50   ` Markus Armbruster
2016-04-29 12:15     ` Eric Blake
2016-04-29 13:03       ` Markus Armbruster
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 12/24] qapi: Document visitor interfaces, add assertions Eric Blake
2016-05-04 14:05   ` [Qemu-devel] [PATCH] fixup! " Eric Blake
2016-05-04 14:49     ` Eric Blake
2016-05-04 15:04     ` Markus Armbruster
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 13/24] tests: Add check-qnull Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 14/24] qapi: Add visit_type_null() visitor Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 15/24] qmp: Support explicit null during visits Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 16/24] spapr_drc: Expose 'null' in qom-get when there is no fdt Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 17/24] qmp: Add qmp_output_visitor_reset() Eric Blake
2016-05-10  4:20   ` [Qemu-devel] [PATCH v16A 17/24] qmp: Don't reuse qmp visitor after grabbing output Eric Blake
2016-05-10  8:18     ` Markus Armbruster
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 18/24] qmp: Tighten output visitor rules Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 19/24] qapi: Split visit_end_struct() into pieces Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 20/24] qapi: Don't pass NULL to printf in string input visitor Eric Blake
2016-04-29  9:03   ` Markus Armbruster
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 21/24] tests/string-input-visitor: Add negative integer tests Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 22/24] qapi: Fix string input visitor handling of invalid list Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 23/24] qapi: Simplify semantics of visit_next_list() Eric Blake
2016-04-28 21:45 ` [Qemu-devel] [PATCH v16 24/24] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2016-04-29 11:13 ` [Qemu-devel] [PATCH v16 00/24] qapi visitor cleanups (post-introspection cleanups subset E) Markus Armbruster
2016-04-29 12:16   ` Eric Blake
2016-04-29 13:09     ` Markus Armbruster
2016-04-29 14:09       ` Eric Blake
2016-05-04 13:54         ` Markus Armbruster
2016-05-04 14:07           ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1461879932-9020-3-git-send-email-eblake@redhat.com \
    --to=eblake@redhat.com \
    --cc=armbru@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.