From patchwork Thu Apr 19 15:01:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 10351007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 55DC46023A for ; Thu, 19 Apr 2018 15:04:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4672828A67 for ; Thu, 19 Apr 2018 15:04:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3B4C828A6F; Thu, 19 Apr 2018 15:04:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9179F28A72 for ; Thu, 19 Apr 2018 15:04:01 +0000 (UTC) Received: from localhost ([::1]:53926 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f9B6O-0008EQ-Mt for patchwork-qemu-devel@patchwork.kernel.org; Thu, 19 Apr 2018 11:04:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49773) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f9B4Y-0006kP-Mz for qemu-devel@nongnu.org; Thu, 19 Apr 2018 11:02:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f9B4W-0002DK-Ko for qemu-devel@nongnu.org; Thu, 19 Apr 2018 11:02:06 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:55084 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f9B4W-0002CB-AW for qemu-devel@nongnu.org; Thu, 19 Apr 2018 11:02:04 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 67FFB81A88A1 for ; Thu, 19 Apr 2018 15:02:03 +0000 (UTC) Received: from localhost (ovpn-112-66.ams2.redhat.com [10.36.112.66]) by smtp.corp.redhat.com (Postfix) with ESMTP id 01AD0215CDA7; Thu, 19 Apr 2018 15:02:02 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Thu, 19 Apr 2018 17:01:45 +0200 Message-Id: <20180419150145.24795-6-marcandre.lureau@redhat.com> In-Reply-To: <20180419150145.24795-1-marcandre.lureau@redhat.com> References: <20180419150145.24795-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 19 Apr 2018 15:02:03 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 19 Apr 2018 15:02:03 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v6 5/5] qobject: modify qobject_ref() to assert on NULL X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: armbru@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , pbonzini@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP While it may be convenient to accept NULL value in qobject_unref() (for similar reasons as free() accepts NULL), it is not such a good idea for qobject_ref(): now assert() on NULL. Some places relied on that behaviour (the monitor request id for example), and it's best to be explicit that NULL is accepted there. We have to rely on testing, and manual inspection of qobject_ref() usage: * block.c: - bdrv_refresh_filename(): guarded - append_open_options(): it depends if qdict values could be NULL, handled for extra safety, might be unnecessary * block/blkdebug.c: - blkdebug_refresh_filename(): depends if qdict values could be NULL, full_open_options could be NULL apparently, handled * block/blkverify.c: guarded * block/{null,nvme}.c: guarded, previous qdict_del() (actually qdict_find()) guarantee non-NULL) * block/quorum.c: full_open_options could be NULL, handled for extra safety, might be unnecessary * monitor: optional "id" case must be handled, in 2 places - monitor_json_emitter(): only called with data != NULL - monitor_qapi_event_queue(): called from func_emit, by qapi events, assert earlier during construction in qobject_output_complete() * qapi/qmp-dispatch.c: if "arguments" exists, it can't be NULL during json parsing * qapi/qobject-input-visitor.c: guarded by assert in visit_type_any() * qapi/qobject-output-visitor.c: guarded by assert() in visit_type_any() qobject_output_complete(): guarded by pre-condition assert() * qmp.c: guarded, error out before if NULL * qobject/q{list,dict}.c: can accept NULL values apparently, what's the reason? how are you supposed to handle that? no test? Some code, such as qdict_flatten_qdict(), assume the value is always non-NULL for example. - tests/*: considered to be covered by make check, not critical - util/keyval.c: guarded, if (!elt[i]) before Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake --- include/qapi/qmp/qobject.h | 7 ++++--- block.c | 9 +++++---- block/blkdebug.c | 3 ++- block/quorum.c | 3 ++- monitor.c | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 25a83aa619..fe8643634c 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -74,9 +74,8 @@ static inline void qobject_init(QObject *obj, QType type) static inline void *qobject_ref_impl(QObject *obj) { - if (obj) { - obj->base.refcnt++; - } + assert(obj); + obj->base.refcnt++; return obj; } @@ -104,6 +103,7 @@ static inline void qobject_unref_impl(QObject *obj) /** * qobject_ref(): Increment QObject's reference count + * @obj: a #QObject or child type instance (must not be NULL) * * Returns: the same @obj. The type of @obj will be propagated to the * return type. @@ -117,6 +117,7 @@ static inline void qobject_unref_impl(QObject *obj) /** * qobject_unref(): Decrement QObject's reference count, deallocate * when it reaches zero + * @obj: a #QObject or children type instance (can be NULL) */ #define qobject_unref(obj) qobject_unref_impl(QOBJECT(obj)) diff --git a/block.c b/block.c index 676e57f562..9f4d7c79af 100644 --- a/block.c +++ b/block.c @@ -5110,8 +5110,9 @@ static bool append_open_options(QDict *d, BlockDriverState *bs) const char *p; for (entry = qdict_first(bs->options); entry; - entry = qdict_next(bs->options, entry)) - { + entry = qdict_next(bs->options, entry)) { + QObject *val; + /* Exclude options for children */ QLIST_FOREACH(child, &bs->children, next) { if (strstart(qdict_entry_key(entry), child->name, &p) @@ -5134,8 +5135,8 @@ static bool append_open_options(QDict *d, BlockDriverState *bs) continue; } - qdict_put_obj(d, qdict_entry_key(entry), - qobject_ref(qdict_entry_value(entry))); + val = qdict_entry_value(entry); + qdict_put_obj(d, qdict_entry_key(entry), val ? qobject_ref(val) : NULL); found_any = true; } diff --git a/block/blkdebug.c b/block/blkdebug.c index 053372c22e..1876a42c0e 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -845,7 +845,8 @@ static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options) opts = qdict_new(); qdict_put_str(opts, "driver", "blkdebug"); - qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options)); + qdict_put(opts, "image", bs->file->bs->full_open_options ? + qobject_ref(bs->file->bs->full_open_options) : NULL); for (e = qdict_first(options); e; e = qdict_next(options, e)) { if (strcmp(qdict_entry_key(e), "x-image")) { diff --git a/block/quorum.c b/block/quorum.c index a5051da56e..0304f248ed 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1083,7 +1083,8 @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options) children = qlist_new(); for (i = 0; i < s->num_children; i++) { qlist_append(children, - qobject_ref(s->children[i]->bs->full_open_options)); + s->children[i]->bs->full_open_options ? + qobject_ref(s->children[i]->bs->full_open_options) : NULL); } opts = qdict_new(); diff --git a/monitor.c b/monitor.c index 46814af533..5dc0c34799 100644 --- a/monitor.c +++ b/monitor.c @@ -4187,7 +4187,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) req_obj = g_new0(QMPRequest, 1); req_obj->mon = mon; - req_obj->id = qobject_ref(id); + req_obj->id = id ? qobject_ref(id) : NULL; req_obj->req = req; req_obj->need_resume = false;