qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC/RFA PATCH] qapi: detect extra members inside structs
@ 2012-03-19 19:29 Paolo Bonzini
  2012-03-19 19:34 ` Anthony Liguori
  2012-03-20  0:28 ` Michael Roth
  0 siblings, 2 replies; 15+ messages in thread
From: Paolo Bonzini @ 2012-03-19 19:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: Michael Roth, anthony, lcapitulino

I noticed that the QMP input visitor does not detect extra members inside
structs.  The outermost arguments struct is handled by the QMP type
checker, but the nested ones go undetected.  That could be a problem
for complex commands such as "transaction".

This patch adds such detection to the QMP input visitor.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
	Is this acceptable or just wrong?

	Other small problems I noticed in running the testsuite:
        why is qemu-ga$(EXESUF) in tests/Makefile and test-qmp-commands
        not run by "make check"?

 qapi/qmp-input-visitor.c |   19 ++++++++++++++++--
 qerror.h                 |    3 +++
 test-qmp-input-visitor.c |   19 +++++++++++++++++++
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index e6b6152..416ab90 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -23,7 +23,8 @@
 typedef struct StackObject
 {
     const QObject *obj;
-    const  QListEntry *entry;
+    const QListEntry *entry;
+    int   left;
 } StackObject;
 
 struct QmpInputVisitor
@@ -31,6 +32,7 @@ struct QmpInputVisitor
     Visitor visitor;
     QObject *obj;
     StackObject stack[QIV_STACK_SIZE];
+    int left;
     int nb_stack;
 };
 
@@ -52,8 +54,13 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
 
     if (qobj) {
         if (name && qobject_type(qobj) == QTYPE_QDICT) {
-            return qdict_get(qobject_to_qdict(qobj), name);
+            qobj = qdict_get(qobject_to_qdict(qobj), name);
+            if (qobj) {
+                assert(qiv->left > 0);
+                qiv->left--;
+            }
         } else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
+            assert(qiv->left == -1);
             return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
         }
     }
@@ -64,10 +70,12 @@ static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
 static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
 {
     qiv->stack[qiv->nb_stack].obj = obj;
+    qiv->stack[qiv->nb_stack].left = qiv->left;
     if (qobject_type(obj) == QTYPE_QLIST) {
         qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
     }
     qiv->nb_stack++;
+    qiv->left = -1;
 
     if (qiv->nb_stack >= QIV_STACK_SIZE) {
         error_set(errp, QERR_BUFFER_OVERRUN);
@@ -77,7 +85,12 @@ static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **err
 
 static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
 {
+    if (qiv->left != -1 && qiv->left != 0) {
+        error_set(errp, QERR_EXTRA_MEMBER);
+        return;
+    }
     qiv->nb_stack--;
+    qiv->left = qiv->stack[qiv->nb_stack].left;
     if (qiv->nb_stack < 0) {
         error_set(errp, QERR_BUFFER_OVERRUN);
         return;
@@ -97,6 +110,7 @@ static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
     }
 
     qmp_input_push(qiv, qobj, errp);
+    qiv->left = qdict_size(qobject_to_qdict(qobj));
     if (error_is_set(errp)) {
         return;
     }
diff --git a/qerror.h b/qerror.h
index e26c635..520cdab 100644
--- a/qerror.h
+++ b/qerror.h
@@ -127,6 +127,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_DUPLICATE_ID \
     "{ 'class': 'DuplicateId', 'data': { 'id': %s, 'object': %s } }"
 
+#define QERR_EXTRA_MEMBER \
+    "{ 'class': 'ExtraInputObjectMember', 'data': {} }"
+
 #define QERR_FD_NOT_FOUND \
     "{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
 
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
index 1996e49..1783759 100644
--- a/test-qmp-input-visitor.c
+++ b/test-qmp-input-visitor.c
@@ -161,6 +161,23 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
     visit_end_struct(v, errp);
 }
 
+static void test_visitor_in_struct_extra(TestInputVisitorData *data,
+                                         const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra' : [ 123, 456, 'def' ] }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    if (p) {
+        g_free(p->string);
+        g_free(p);
+    }
+}
+
 static void test_visitor_in_struct(TestInputVisitorData *data,
                                    const void *unused)
 {
@@ -278,6 +295,8 @@ int main(int argc, char **argv)
                             &in_visitor_data, test_visitor_in_struct);
     input_visitor_test_add("/visitor/input/struct-nested",
                             &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/struct-extra",
+                            &in_visitor_data, test_visitor_in_struct_extra);
     input_visitor_test_add("/visitor/input/list",
                             &in_visitor_data, test_visitor_in_list);
     input_visitor_test_add("/visitor/input/union",
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-03-20 19:33 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-19 19:29 [Qemu-devel] [RFC/RFA PATCH] qapi: detect extra members inside structs Paolo Bonzini
2012-03-19 19:34 ` Anthony Liguori
2012-03-19 19:51   ` Paolo Bonzini
2012-03-19 19:56     ` Anthony Liguori
2012-03-19 20:22       ` Eric Blake
2012-03-19 20:30         ` Anthony Liguori
2012-03-19 20:43           ` Luiz Capitulino
2012-03-19 22:29             ` Michael Roth
2012-03-19 22:38               ` Anthony Liguori
2012-03-19 23:45                 ` Michael Roth
2012-03-20  0:49                   ` Anthony Liguori
2012-03-20 12:15                     ` Luiz Capitulino
2012-03-20 19:33                       ` Anthony Liguori
2012-03-20 17:31       ` Paolo Bonzini
2012-03-20  0:28 ` Michael Roth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).