From 911ee36d411ee9b3540855642b53219b6a974992 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 9 Jun 2016 10:48:33 -0600 Subject: qemu-img: Don't leak errors when outputting JSON If our JSON output ever encounters an error, we would just silently leak the error object. Instead, assert that our usage won't fail. Signed-off-by: Eric Blake Message-Id: <1465490926-28625-3-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qemu-img.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'qemu-img.c') diff --git a/qemu-img.c b/qemu-img.c index 3322a1e5fc..debd7f1383 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -490,12 +490,11 @@ fail: static void dump_json_image_check(ImageCheck *check, bool quiet) { - Error *local_err = NULL; QString *str; QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; visit_type_ImageCheck(qmp_output_get_visitor(ov), NULL, &check, - &local_err); + &error_abort); obj = qmp_output_get_qobject(ov); str = qobject_to_json_pretty(obj); assert(str != NULL); @@ -2181,12 +2180,11 @@ static void dump_snapshots(BlockDriverState *bs) static void dump_json_image_info_list(ImageInfoList *list) { - Error *local_err = NULL; QString *str; QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; visit_type_ImageInfoList(qmp_output_get_visitor(ov), NULL, &list, - &local_err); + &error_abort); obj = qmp_output_get_qobject(ov); str = qobject_to_json_pretty(obj); assert(str != NULL); @@ -2198,11 +2196,11 @@ static void dump_json_image_info_list(ImageInfoList *list) static void dump_json_image_info(ImageInfo *info) { - Error *local_err = NULL; QString *str; QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; - visit_type_ImageInfo(qmp_output_get_visitor(ov), NULL, &info, &local_err); + visit_type_ImageInfo(qmp_output_get_visitor(ov), NULL, &info, + &error_abort); obj = qmp_output_get_qobject(ov); str = qobject_to_json_pretty(obj); assert(str != NULL); -- cgit v1.2.3 From 1830f22a6777cedaccd67a08f675d30f7a85ebfd Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 9 Jun 2016 10:48:40 -0600 Subject: qmp-output-visitor: Favor new visit_free() function Now that we have a polymorphic visit_free(), we no longer need qmp_output_visitor_cleanup(); however, we still need to expose the subtype for qmp_output_get_qobject(). Signed-off-by: Eric Blake Message-Id: <1465490926-28625-10-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qemu-img.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'qemu-img.c') diff --git a/qemu-img.c b/qemu-img.c index debd7f1383..728f471801 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -500,7 +500,7 @@ static void dump_json_image_check(ImageCheck *check, bool quiet) assert(str != NULL); qprintf(quiet, "%s\n", qstring_get_str(str)); qobject_decref(obj); - qmp_output_visitor_cleanup(ov); + visit_free(qmp_output_get_visitor(ov)); QDECREF(str); } @@ -2190,7 +2190,7 @@ static void dump_json_image_info_list(ImageInfoList *list) assert(str != NULL); printf("%s\n", qstring_get_str(str)); qobject_decref(obj); - qmp_output_visitor_cleanup(ov); + visit_free(qmp_output_get_visitor(ov)); QDECREF(str); } @@ -2206,7 +2206,7 @@ static void dump_json_image_info(ImageInfo *info) assert(str != NULL); printf("%s\n", qstring_get_str(str)); qobject_decref(obj); - qmp_output_visitor_cleanup(ov); + visit_free(qmp_output_get_visitor(ov)); QDECREF(str); } -- cgit v1.2.3 From 3b098d56979d2f7fd707c5be85555d114353a28d Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 9 Jun 2016 10:48:43 -0600 Subject: qapi: Add new visit_complete() function Making each output visitor provide its own output collection function was the only remaining reason for exposing visitor sub-types to the rest of the code base. Add a polymorphic visit_complete() function which is a no-op for input visitors, and which populates an opaque pointer for output visitors. For maximum type-safety, also add a parameter to the output visitor constructors with a type-correct version of the output pointer, and assert that the two uses match. This approach was considered superior to either passing the output parameter only during construction (action at a distance during visit_free() feels awkward) or only during visit_complete() (defeating type safety makes it easier to use incorrectly). Most callers were function-local, and therefore a mechanical conversion; the testsuite was a bit trickier, but the previous cleanup patch minimized the churn here. The visit_complete() function may be called at most once; doing so lets us use transfer semantics rather than duplication or ref-count semantics to get the just-built output back to the caller, even though it means our behavior is not idempotent. Generated code is simplified as follows for events: |@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP | QDict *qmp; | Error *err = NULL; | QMPEventFuncEmit emit; |- QmpOutputVisitor *qov; |+ QObject *obj; | Visitor *v; | q_obj_ACPI_DEVICE_OST_arg param = { | info |@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP | | qmp = qmp_event_build_dict("ACPI_DEVICE_OST"); | |- qov = qmp_output_visitor_new(); |- v = qmp_output_get_visitor(qov); |+ v = qmp_output_visitor_new(&obj); | | visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err); | if (err) { |@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP | goto out; | } | |- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov)); |+ visit_complete(v, &obj); |+ qdict_put_obj(qmp, "data", obj); | emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err); and for commands: | { | Error *err = NULL; |- QmpOutputVisitor *qov = qmp_output_visitor_new(); | Visitor *v; | |- v = qmp_output_get_visitor(qov); |+ v = qmp_output_visitor_new(ret_out); | visit_type_AddfdInfo(v, "unused", &ret_in, &err); |- if (err) { |- goto out; |+ if (!err) { |+ visit_complete(v, ret_out); | } |- *ret_out = qmp_output_get_qobject(qov); |- |-out: | error_propagate(errp, err); Signed-off-by: Eric Blake Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- qemu-img.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'qemu-img.c') diff --git a/qemu-img.c b/qemu-img.c index 728f471801..4dfb27df37 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -491,16 +491,16 @@ fail: static void dump_json_image_check(ImageCheck *check, bool quiet) { QString *str; - QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; - visit_type_ImageCheck(qmp_output_get_visitor(ov), NULL, &check, - &error_abort); - obj = qmp_output_get_qobject(ov); + Visitor *v = qmp_output_visitor_new(&obj); + + visit_type_ImageCheck(v, NULL, &check, &error_abort); + visit_complete(v, &obj); str = qobject_to_json_pretty(obj); assert(str != NULL); qprintf(quiet, "%s\n", qstring_get_str(str)); qobject_decref(obj); - visit_free(qmp_output_get_visitor(ov)); + visit_free(v); QDECREF(str); } @@ -2181,32 +2181,32 @@ static void dump_snapshots(BlockDriverState *bs) static void dump_json_image_info_list(ImageInfoList *list) { QString *str; - QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; - visit_type_ImageInfoList(qmp_output_get_visitor(ov), NULL, &list, - &error_abort); - obj = qmp_output_get_qobject(ov); + Visitor *v = qmp_output_visitor_new(&obj); + + visit_type_ImageInfoList(v, NULL, &list, &error_abort); + visit_complete(v, &obj); str = qobject_to_json_pretty(obj); assert(str != NULL); printf("%s\n", qstring_get_str(str)); qobject_decref(obj); - visit_free(qmp_output_get_visitor(ov)); + visit_free(v); QDECREF(str); } static void dump_json_image_info(ImageInfo *info) { QString *str; - QmpOutputVisitor *ov = qmp_output_visitor_new(); QObject *obj; - visit_type_ImageInfo(qmp_output_get_visitor(ov), NULL, &info, - &error_abort); - obj = qmp_output_get_qobject(ov); + Visitor *v = qmp_output_visitor_new(&obj); + + visit_type_ImageInfo(v, NULL, &info, &error_abort); + visit_complete(v, &obj); str = qobject_to_json_pretty(obj); assert(str != NULL); printf("%s\n", qstring_get_str(str)); qobject_decref(obj); - visit_free(qmp_output_get_visitor(ov)); + visit_free(v); QDECREF(str); } -- cgit v1.2.3