From: Markus Armbruster <armbru@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: qemu-devel@nongnu.org, peterx@redhat.com
Subject: Re: [Qemu-devel] [PATCH 07/12] json-parser: always set an error if return NULL
Date: Tue, 17 Jul 2018 09:06:12 +0200 [thread overview]
Message-ID: <87wotufijf.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20180706121354.2021-8-marcandre.lureau@redhat.com> ("Marc-André Lureau"'s message of "Fri, 6 Jul 2018 14:13:49 +0200")
Marc-André Lureau <marcandre.lureau@redhat.com> writes:
> Let's make json_parser_parse_err() suck less, and simplify caller
> error handling.
Missing:
* monitor.c handle_qmp_command(): drop workaround
> * qga/main.c process_event() doesn't need further changes after
> previous cleanup.
"Doesn't need further changes" yes, but I think it could use one.
Consider:
obj = json_parser_parse_err(tokens, NULL, &err);
if (err) {
goto err;
}
qdict = qobject_to(QDict, obj);
if (!qdict) {
error_setg(&err, QERR_JSON_PARSING);
goto err;
}
Before this patch, we get to the error_setg() when
json_parser_parse_err() fails without setting an error, and when it
succeeds but returns anything but a dictionary. QERR_JSON_PARSING is
appropriate for the first case, but not the second.
This patch removes the first case. Please improve the error message.
> * qobject/json-parser.c json_parser_parse()
> Ignores the error.
Stupid wrapper that's used exactly once, in libqtest.c. Let's use
json_parser_parse_err() there, and drop the wrapper. Let's rename
json_parser_parse_err() to json_parser_parse() then.
> * qobject/qjson.c qobject_from_jsonv() via parse_json()
> - qobject_from_json()
> ~ block.c parse_json_filename() - removed workaround
> ~ block/rbd.c - abort (generated json - should never fail)
> ~ qapi/qobject-input-visitor.c - removed workaround
> ~ tests/check-qjson.c - abort, ok
To be precise, we pass &error_abort and either assert or crash when it
returns null. Okay. Same for other instances of "abort, ok" below.
There are a few instances that don't abort. First one when !utf8_out:
obj = qobject_from_json(json_in, utf8_out ? &error_abort : NULL);
if (utf8_out) {
str = qobject_to(QString, obj);
g_assert(str);
g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
} else {
g_assert(!obj);
}
qobject_unref(obj);
It ignores the error. Okay.
Next one:
static void unterminated_string(void)
{
Error *err = NULL;
QObject *obj = qobject_from_json("\"abc", &err);
g_assert(!err); /* BUG */
g_assert(obj == NULL);
}
This patch should fix the BUG. We'll see at [*] below why it doens't.
> ~ tests/test-visitor-serialization.c - abort, ok
>
> - qobject_from_jsonf()
This is called qobject_from_jsonf_nofail() since commit f3e9cc9f7a1, and
became the obvious wrapper around qobject_from_vjsonf_nofail() in commit
74670550ee0. Please mention both new names.
I guess the commit message needs more updates for these recent changes
below, but I'm glossing over that now, along with much of the patch,
because I think I've found something more serious, explained at the end
of the patch.
> Now dies in error_handle_fatal() instead of the assertion.
Which assertion? Ah, the one in qobject_from_vjsonf_nofail().
The assertion is now dead, isn't it?
> Only used in tests, ok.
>
> - tests/test-qobject-input-visitor.c
> - tests/libqtest.c qmp_fd_sendv()
> Passes &error_abort, does nothing when qobject_from_jsonv() returns
> null. The fix makes this catch invalid JSON instead of silently
> ignoring it.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> block.c | 5 -----
> monitor.c | 4 ----
> qapi/qobject-input-visitor.c | 5 -----
> qobject/json-parser.c | 8 +++++++-
> 4 files changed, 7 insertions(+), 15 deletions(-)
>
> diff --git a/block.c b/block.c
> index ac8b3a3511..9046d66465 100644
> --- a/block.c
> +++ b/block.c
> @@ -1478,11 +1478,6 @@ static QDict *parse_json_filename(const char *filename, Error **errp)
>
> options_obj = qobject_from_json(filename, errp);
> if (!options_obj) {
> - /* Work around qobject_from_json() lossage TODO fix that */
> - if (errp && !*errp) {
> - error_setg(errp, "Could not parse the JSON options");
> - return NULL;
> - }
> error_prepend(errp, "Could not parse the JSON options: ");
> return NULL;
> }
> diff --git a/monitor.c b/monitor.c
> index ec40a80d81..a3efe96d1d 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -4112,10 +4112,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
> QMPRequest *req_obj;
>
> req = json_parser_parse_err(tokens, NULL, &err);
> - if (!req && !err) {
> - /* json_parser_parse_err() sucks: can fail without setting @err */
> - error_setg(&err, QERR_JSON_PARSING);
> - }
>
> qdict = qobject_to(QDict, req);
> if (qdict) {
> diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
> index da57f4cc24..3e88b27f9e 100644
> --- a/qapi/qobject-input-visitor.c
> +++ b/qapi/qobject-input-visitor.c
> @@ -725,11 +725,6 @@ Visitor *qobject_input_visitor_new_str(const char *str,
> if (is_json) {
> obj = qobject_from_json(str, errp);
> if (!obj) {
> - /* Work around qobject_from_json() lossage TODO fix that */
> - if (errp && !*errp) {
> - error_setg(errp, "JSON parse error");
> - return NULL;
> - }
> return NULL;
> }
> args = qobject_to(QDict, obj);
> diff --git a/qobject/json-parser.c b/qobject/json-parser.c
> index a5aa790d62..82c3167629 100644
> --- a/qobject/json-parser.c
> +++ b/qobject/json-parser.c
> @@ -24,6 +24,7 @@
> #include "qapi/qmp/json-parser.h"
> #include "qapi/qmp/json-lexer.h"
> #include "qapi/qmp/json-streamer.h"
> +#include "qapi/qmp/qerror.h"
>
> typedef struct JSONParserContext
> {
> @@ -591,7 +592,12 @@ QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
{
JSONParserContext *ctxt = parser_context_new(tokens);
QObject *result;
if (!ctxt) {
return NULL;
[*] Still returns null without setting an error. Two cases lumped into
one: "no tokens due to empty input (not an error)", and "no tokens due
to lexical error". This is not the spot to distinguish the two, it
needs to be done in its callers. I figure the sane contract for
json_parser_parse_err() would be
* If @tokens is null, return null.
* Else if @tokens parse okay, return the parse tree.
* Else set an error and return null.
But then "always set an error if return NULL" is not possible. Ideas?
}
>
> result = parse_value(ctxt, ap);
>
> - error_propagate(errp, ctxt->err);
> + if (!result && !ctxt->err) {
> + /* TODO: improve error reporting */
> + error_setg(errp, QERR_JSON_PARSING);
> + } else {
> + error_propagate(errp, ctxt->err);
> + }
>
> parser_context_free(ctxt);
next prev parent reply other threads:[~2018-07-17 7:06 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-06 12:13 [Qemu-devel] [PATCH 00/12] RFC: monitor: various code simplification and fixes Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 01/12] tests: change /0.15/* tests to /qmp/* Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 02/12] monitor: consitify qmp_send_response() QDict argument Marc-André Lureau
2018-07-12 12:27 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 03/12] qmp: constify qmp_is_oob() Marc-André Lureau
2018-07-12 12:27 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 04/12] Revert "qmp: isolate responses into io thread" Marc-André Lureau
2018-07-12 13:14 ` Markus Armbruster
2018-07-12 13:32 ` Marc-André Lureau
2018-07-12 14:27 ` Peter Xu
2018-07-06 12:13 ` [Qemu-devel] [PATCH 05/12] monitor: no need to save need_resume Marc-André Lureau
2018-07-17 5:38 ` Markus Armbruster
2018-07-17 6:05 ` Peter Xu
2018-07-06 12:13 ` [Qemu-devel] [PATCH 06/12] qga: process_event() simplification and leak fix Marc-André Lureau
2018-07-17 5:53 ` Markus Armbruster
2018-07-17 9:27 ` Marc-André Lureau
2018-07-17 12:14 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 07/12] json-parser: always set an error if return NULL Marc-André Lureau
2018-07-17 7:06 ` Markus Armbruster [this message]
2018-07-19 16:59 ` Marc-André Lureau
2018-07-20 6:03 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 08/12] json-lexer: make it safe to call multiple times Marc-André Lureau
2018-07-17 7:22 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 09/12] tests: add a few qemu-qmp tests Marc-André Lureau
2018-07-17 8:01 ` Markus Armbruster
2018-07-17 9:57 ` Marc-André Lureau
2018-07-17 13:15 ` Markus Armbruster
2018-07-19 17:20 ` Marc-André Lureau
2018-07-06 12:13 ` [Qemu-devel] [PATCH 10/12] tests: add a qmp success-response test Marc-André Lureau
2018-07-17 15:12 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 11/12] qga: process_event() simplification Marc-André Lureau
2018-07-17 15:25 ` Markus Armbruster
2018-07-06 12:13 ` [Qemu-devel] [PATCH 12/12] RFC: qmp: rework 'id' handling Marc-André Lureau
2018-07-17 16:05 ` Markus Armbruster
2018-07-19 17:45 ` Marc-André Lureau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87wotufijf.fsf@dusky.pond.sub.org \
--to=armbru@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=peterx@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.