qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v5 28/46] qapi: Rework deallocation of partial struc


From: Eric Blake
Subject: [Qemu-devel] [PATCH v5 28/46] qapi: Rework deallocation of partial struct
Date: Mon, 21 Sep 2015 15:57:44 -0600

Commit cee2dedb noticed that if you have a partial flat union
(such as if an input parse failed due to a missing
discriminator), calling the dealloc visitor could result in
trying to dereference the NULL pointer. But the fix it proposed
requires the use of a 'data' member in the union, which may or
may not be the same size as other branches of the union
(consider a 32-bit platform where one of the branches is an
int64), so it feels fairly dirty.  A better, and much shorter,
fix is to tweak all of the generated visit_type_implicit_FOO()
functions to avoid dereferencing NULL in the first place, to
not visit the fields if the struct pointer itself is not present,
at which point we no longer even need visit_start_union(), and
no one was implementing visit_end_union() callbacks. The change
keeps the contract that any successful use of
visit_start_implicit_struct() will be paired with a matching
visit_end_implicit_struct(), even if intermediate processing is
skipped.

Signed-off-by: Eric Blake <address@hidden>
---
 include/qapi/visitor-impl.h |  5 -----
 include/qapi/visitor.h      | 12 ------------
 qapi/qapi-dealloc-visitor.c | 26 --------------------------
 qapi/qapi-visit-core.c      | 15 ---------------
 scripts/qapi-visit.py       | 10 +++-------
 5 files changed, 3 insertions(+), 65 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 590b067..b87d9a3 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -71,11 +71,6 @@ struct Visitor
     /* May be NULL; most useful for input visitors. */
     void (*optional)(Visitor *v, bool *present, const char *name);

-    /* FIXME - needs to be removed */
-    bool (*start_union)(Visitor *v, bool data_present, Error **errp);
-    /* FIXME - needs to be removed */
-    void (*end_union)(Visitor *v, bool data_present, Error **errp);
-
     /* Only required to visit uint64 differently than (*type_int)().  */
     void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name,
                         Error **errp);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 2deeb7f..284a978 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -230,16 +230,4 @@ void visit_type_number(Visitor *v, double *obj, const char 
*name,
  */
 void visit_type_any(Visitor *v, QObject **obj, const char *name, Error **errp);

-/**
- * Mark the start of visiting the branches of a union. Return true if
- * @data_present.
- * FIXME: Should not be needed
- */
-bool visit_start_union(Visitor *v, bool data_present, Error **errp);
-/**
- * Mark the end of union branches, after visit_start_union().
- * FIXME: Should not be needed
- */
-void visit_end_union(Visitor *v, bool data_present, Error **errp);
-
 #endif
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index 737deab..4989f50 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -171,31 +171,6 @@ static void qapi_dealloc_type_enum(Visitor *v, int *obj,
 {
 }

-/* If there's no data present, the dealloc visitor has nothing to free.
- * Thus, indicate to visitor code that the subsequent union fields can
- * be skipped. This is not an error condition, since the cleanup of the
- * rest of an object can continue unhindered, so leave errp unset in
- * these cases.
- *
- * NOTE: In cases where we're attempting to deallocate an object that
- * may have missing fields, the field indicating the union type may
- * be missing. In such a case, it's possible we don't have enough
- * information to differentiate data_present == false from a case where
- * data *is* present but happens to be a scalar with a value of 0.
- * This is okay, since in the case of the dealloc visitor there's no
- * work that needs to done in either situation.
- *
- * The current inability in QAPI code to more thoroughly verify a union
- * type in such cases will likely need to be addressed if we wish to
- * implement this interface for other types of visitors in the future,
- * however.
- */
-static bool qapi_dealloc_start_union(Visitor *v, bool data_present,
-                                     Error **errp)
-{
-    return data_present;
-}
-
 Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
 {
     return &v->visitor;
@@ -226,7 +201,6 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
     v->visitor.type_number = qapi_dealloc_type_number;
     v->visitor.type_any = qapi_dealloc_type_anything;
     v->visitor.type_size = qapi_dealloc_type_size;
-    v->visitor.start_union = qapi_dealloc_start_union;

     QTAILQ_INIT(&v->stack);

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 2594147..020ea34 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -58,21 +58,6 @@ void visit_end_list(Visitor *v, Error **errp)
     v->end_list(v, errp);
 }

-bool visit_start_union(Visitor *v, bool data_present, Error **errp)
-{
-    if (v->start_union) {
-        return v->start_union(v, data_present, errp);
-    }
-    return true;
-}
-
-void visit_end_union(Visitor *v, bool data_present, Error **errp)
-{
-    if (v->end_union) {
-        v->end_union(v, data_present, errp);
-    }
-}
-
 bool visit_optional(Visitor *v, bool *present, const char *name)
 {
     if (v->optional) {
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 55f6430..d94b34e 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -51,7 +51,9 @@ static void visit_type_implicit_%(c_type)s(Visitor *v, 
%(c_type)s **obj, Error *

     visit_start_implicit_struct(v, (void **)obj, sizeof(%(c_type)s), &err);
     if (!err) {
-        visit_type_%(c_type)s_fields(v, obj, &err);
+        if (!obj || *obj) {
+            visit_type_%(c_type)s_fields(v, obj, &err);
+        }
         visit_end_implicit_struct(v, err ? NULL : &err);
     }
     error_propagate(errp, err);
@@ -270,9 +272,6 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, 
const char *name, Error
     if (err) {
         goto out_obj;
     }
-    if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
-        goto out_obj;
-    }
     switch ((*obj)->%(c_name)s) {
 ''',
                  c_type=variants.tag_member.type.c_name(),
@@ -311,9 +310,6 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, 
const char *name, Error
         abort();
     }
 out_obj:
-    error_propagate(errp, err);
-    err = NULL;
-    visit_end_union(v, !!(*obj)->data, &err);
     visit_end_struct(v, err ? NULL : &err);
 out:
     error_propagate(errp, err);
-- 
2.4.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]