Patchwork [06/21] qapi: dealloc visitor, fix premature free and iteration logic

login
register
mail settings
Submitter Luiz Capitulino
Date Sept. 28, 2011, 2:44 p.m.
Message ID <1317221085-5825-7-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/116819/
State New
Headers show

Comments

Luiz Capitulino - Sept. 28, 2011, 2:44 p.m.
From: Michael Roth <mdroth@linux.vnet.ibm.com>

Currently we do 3 things wrong:

1) The list iterator, in practice, is used in a manner where the pointer
we pass in is the same as the pointer we assign the output to from
visit_next_list(). This causes an infinite loop where we keep freeing
the same structures.

2) We attempt to free list->value rather than list. visit_type_<type>
handles this. We should only be concerned with the containing list.

3) We free prematurely: iterator function will continue accessing values
we've already freed.

This patch should fix all of these issues. QmpOutputVisitor also suffers
from 1).

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qapi/qapi-dealloc-visitor.c |   20 +++++++++++++++-----
 1 files changed, 15 insertions(+), 5 deletions(-)
Anthony Liguori - Sept. 29, 2011, 12:49 p.m.
On 09/28/2011 09:44 AM, Luiz Capitulino wrote:
> From: Michael Roth<mdroth@linux.vnet.ibm.com>
>
> Currently we do 3 things wrong:
>
> 1) The list iterator, in practice, is used in a manner where the pointer
> we pass in is the same as the pointer we assign the output to from
> visit_next_list(). This causes an infinite loop where we keep freeing
> the same structures.
>
> 2) We attempt to free list->value rather than list. visit_type_<type>
> handles this. We should only be concerned with the containing list.
>
> 3) We free prematurely: iterator function will continue accessing values
> we've already freed.
>
> This patch should fix all of these issues. QmpOutputVisitor also suffers
> from 1).
>
> Signed-off-by: Michael Roth<mdroth@linux.vnet.ibm.com>
> Signed-off-by: Luiz Capitulino<lcapitulino@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   qapi/qapi-dealloc-visitor.c |   20 +++++++++++++++-----
>   1 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
> index f629061..6b586ad 100644
> --- a/qapi/qapi-dealloc-visitor.c
> +++ b/qapi/qapi-dealloc-visitor.c
> @@ -26,6 +26,7 @@ struct QapiDeallocVisitor
>   {
>       Visitor visitor;
>       QTAILQ_HEAD(, StackEntry) stack;
> +    bool is_list_head;
>   };
>
>   static QapiDeallocVisitor *to_qov(Visitor *v)
> @@ -70,15 +71,24 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
>
>   static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
>   {
> +    QapiDeallocVisitor *qov = to_qov(v);
> +    qov->is_list_head = true;
>   }
>
> -static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
> +static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
>                                              Error **errp)
>   {
> -    GenericList *retval = *list;
> -    g_free(retval->value);
> -    *list = retval->next;
> -    return retval;
> +    GenericList *list = *listp;
> +    QapiDeallocVisitor *qov = to_qov(v);
> +
> +    if (!qov->is_list_head) {
> +        *listp = list->next;
> +        g_free(list);
> +        return *listp;
> +    }
> +
> +    qov->is_list_head = false;
> +    return list;
>   }
>
>   static void qapi_dealloc_end_list(Visitor *v, Error **errp)

Patch

diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index f629061..6b586ad 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -26,6 +26,7 @@  struct QapiDeallocVisitor
 {
     Visitor visitor;
     QTAILQ_HEAD(, StackEntry) stack;
+    bool is_list_head;
 };
 
 static QapiDeallocVisitor *to_qov(Visitor *v)
@@ -70,15 +71,24 @@  static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
 
 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
 {
+    QapiDeallocVisitor *qov = to_qov(v);
+    qov->is_list_head = true;
 }
 
-static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
                                            Error **errp)
 {
-    GenericList *retval = *list;
-    g_free(retval->value);
-    *list = retval->next;
-    return retval;
+    GenericList *list = *listp;
+    QapiDeallocVisitor *qov = to_qov(v);
+
+    if (!qov->is_list_head) {
+        *listp = list->next;
+        g_free(list);
+        return *listp;
+    }
+
+    qov->is_list_head = false;
+    return list;
 }
 
 static void qapi_dealloc_end_list(Visitor *v, Error **errp)