summaryrefslogtreecommitdiff
path: root/qobject/qjson.c
AgeCommit message (Collapse)Author
2020-04-30qobject: Eliminate qdict_iter(), use qdict_first(), qdict_next()Markus Armbruster
qdict_iter() has just three uses and no test coverage. Replace by qdict_first(), qdict_next() for more concise code and less type punning. Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20200415083048.14339-5-armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2020-04-30qobject: Eliminate qlist_iter(), use QLIST_FOREACH_ENTRY() insteadMarkus Armbruster
qlist_iter() has just three uses outside tests/. Replace by QLIST_FOREACH_ENTRY() for more concise code and less type punning. Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20200415083048.14339-4-armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2020-04-30qobject: Factor out helper json_pretty_newline()Markus Armbruster
Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20200415083048.14339-3-armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> [Coding style in moved code tidied up]
2018-08-24json: Clean up headersMarkus Armbruster
The JSON parser has three public headers, json-lexer.h, json-parser.h, json-streamer.h. They all contain stuff that is of no interest outside qobject/json-*.c. Collect the public interface in include/qapi/qmp/json-parser.h, and everything else in qobject/json-parser-int.h. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180823164025.12553-54-armbru@redhat.com>
2018-08-24qjson: Have qobject_from_json() & friends reject empty and blankMarkus Armbruster
The last case where qobject_from_json() & friends return null without setting an error is empty or blank input. Callers: * block.c's parse_json_protocol() reports "Could not parse the JSON options". It's marked as a work-around, because it also covered actual bugs, but they got fixed in the previous few commits. * qobject_input_visitor_new_str() reports "JSON parse error". Also marked as work-around. The recent fixes have made this unreachable, because it currently gets called only for input starting with '{'. * check-qjson.c's empty_input() and blank_input() demonstrate the behavior. * The other callers are not affected since they only pass input with exactly one JSON value or, in the case of negative tests, one error. Fail with "Expecting a JSON value" instead of returning null, and simplify callers. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180823164025.12553-48-armbru@redhat.com>
2018-08-24qjson: Fix qobject_from_json() & friends for multiple valuesMarkus Armbruster
qobject_from_json() & friends use the consume_json() callback to receive either a value or an error from the parser. When they are fed a string that contains more than either one JSON value or one JSON syntax error, consume_json() gets called multiple times. When the last call receives a value, qobject_from_json() returns that value. Any other values are leaked. When any call receives an error, qobject_from_json() sets the first error received. Any other errors are thrown away. When values follow errors, qobject_from_json() returns both a value and sets an error. That's bad. Impact: * block.c's parse_json_protocol() ignores and leaks the value. It's used to to parse pseudo-filenames starting with "json:". The pseudo-filenames can come from the user or from image meta-data such as a QCOW2 image's backing file name. * vl.c's parse_display_qapi() ignores and leaks the error. It's used to parse the argument of command line option -display. * vl.c's main() case QEMU_OPTION_blockdev ignores the error and leaves it in @err. main() will then pass a pointer to a non-null Error * to net_init_clients(), which is forbidden. It can lead to assertion failure or other misbehavior. * check-qjson.c's multiple_values() demonstrates the badness. * The other callers are not affected since they only pass strings with exactly one JSON value or, in the case of negative tests, one error. The impact on the _nofail() functions is relatively harmless. They abort when any call receives an error. Else they return the last value, and leak the others, if any. Fix consume_json() as follows. On the first call, save value and error as before. On subsequent calls, if any, don't save them. If the first call saved a value, the next call, if any, replaces the value by an "Expecting at most one JSON value" error. Take care not to leak values or errors that aren't saved. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180823164025.12553-44-armbru@redhat.com>
2018-08-24json: Redesign the callback to consume JSON valuesMarkus Armbruster
The classical way to structure parser and lexer is to have the client call the parser to get an abstract syntax tree, the parser call the lexer to get the next token, and the lexer call some function to get input characters. Another way to structure them would be to have the client feed characters to the lexer, the lexer feed tokens to the parser, and the parser feed abstract syntax trees to some callback provided by the client. This way is more easily integrated into an event loop that dispatches input characters as they arrive. Our JSON parser is kind of between the two. The lexer feeds tokens to a "streamer" instead of a real parser. The streamer accumulates tokens until it got the sequence of tokens that comprise a single JSON value (it counts curly braces and square brackets to decide). It feeds those token sequences to a callback provided by the client. The callback passes each token sequence to the parser, and gets back an abstract syntax tree. I figure it was done that way to make a straightforward recursive descent parser possible. "Get next token" becomes "pop the first token off the token sequence". Drawback: we need to store a complete token sequence. Each token eats 13 + input characters + malloc overhead bytes. Observations: 1. This is not the only way to use recursive descent. If we replaced "get next token" by a coroutine yield, we could do without a streamer. 2. The lexer reports errors by passing a JSON_ERROR token to the streamer. This communicates the offending input characters and their location, but no more. 3. The streamer reports errors by passing a null token sequence to the callback. The (already poor) lexical error information is thrown away. 4. Having the callback receive a token sequence duplicates the code to convert token sequence to abstract syntax tree in every callback. 5. Known bug: the streamer silently drops incomplete token sequences. This commit rectifies 4. by lifting the call of the parser from the callbacks into the streamer. Later commits will address 3. and 5. The lifting removes a bug from qjson.c's parse_json(): it passed a pointer to a non-null Error * in certain cases, as demonstrated by check-qjson.c. json_parser_parse() is now unused. It's a stupid wrapper around json_parser_parse_err(). Drop it, and rename json_parser_parse_err() to json_parser_parse(). Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180823164025.12553-35-armbru@redhat.com>
2018-08-16qobject: qobject_from_jsonv() is dangerous, hide it awayMarkus Armbruster
qobject_from_jsonv() takes ownership of %p arguments. On failure, we can't generally know whether we failed before or after %p, so ownership becomes indeterminate. To avoid leaks, callers passing %p must terminate on error, e.g. by passing &error_abort. Trap for the unwary; document and give the function internal linkage. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180806065344.7103-11-armbru@redhat.com>
2018-08-16qobject: New qobject_from_vjsonf_nofail(), qdict_from_vjsonf_nofail()Markus Armbruster
Every printf()-like function sooner or later needs its vprintf()-like buddy. The next commit will need qobject_from_jsonf_nofail()'s buddy, and qdict_from_jsonf_nofail()'s buddy will be used later in this series. Add both. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180806065344.7103-8-armbru@redhat.com>
2018-08-16qobject: Replace qobject_from_jsonf() by qobject_from_jsonf_nofail()Markus Armbruster
Commit ab45015a968 "qobject: Let qobject_from_jsonf() fail instead of abort" fails to accomplish its stated aim: the function can still abort due to its use of &error_abort. Its rationale for letting it fail is that all remaining users cope fine with failure. Well, they're just fine with aborting, too; it's what they do on failure. Simply reverting the broken commit would bring back the unfortunate asymmetry between qobject_from_jsonf() and qobject_from_jsonv(): one aborts, the other returns null. So also rename it to qobject_from_jsonf_nofail(). Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180806065344.7103-7-armbru@redhat.com>
2018-07-03qobject: Let qobject_from_jsonf() fail instead of abortMarkus Armbruster
qobject_from_jsonf() aborts on error, unlike qobject_from_jsonv(), which returns null. Since all remaining users of qobject_from_jsonf() cope fine with null, change it to return null. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180703085358.13941-30-armbru@redhat.com>
2018-07-03qobject: New qdict_from_jsonf_nofail()Markus Armbruster
Many uses of qobject_from_jsonf() convert JSON objects. Create new convenience function qdict_from_jsonf_nofail() that includes the conversion to QDict. The next few commits will put it to use. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180703085358.13941-22-armbru@redhat.com>
2018-05-04qobject: Replace qobject_incref/QINCREF qobject_decref/QDECREFMarc-André Lureau
Now that we can safely call QOBJECT() on QObject * as well as its subtypes, we can have macros qobject_ref() / qobject_unref() that work everywhere instead of having to use QINCREF() / QDECREF() for QObject and qobject_incref() / qobject_decref() for its subtypes. The replacement is mechanical, except I broke a long line, and added a cast in monitor_qmp_cleanup_req_queue_locked(). Unlike qobject_decref(), qobject_unref() doesn't accept void *. Note that the new macros evaluate their argument exactly once, thus no need to shout them. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180419150145.24795-4-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Rebased, semantic conflict resolved, commit message improved] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-03-19qapi: Replace qobject_to_X(o) by qobject_to(X, o)Max Reitz
This patch was generated using the following Coccinelle script: @@ expression Obj; @@ ( - qobject_to_qnum(Obj) + qobject_to(QNum, Obj) | - qobject_to_qstring(Obj) + qobject_to(QString, Obj) | - qobject_to_qdict(Obj) + qobject_to(QDict, Obj) | - qobject_to_qlist(Obj) + qobject_to(QList, Obj) | - qobject_to_qbool(Obj) + qobject_to(QBool, Obj) ) and a bit of manual fix-up for overly long lines and three places in tests/check-qjson.c that Coccinelle did not find. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Message-Id: <20180224154033.29559-4-mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> [eblake: swap order from qobject_to(o, X), rebase to master, also a fix to latent false-positive compiler complaint about hw/i386/acpi-build.c] Signed-off-by: Eric Blake <eblake@redhat.com>
2018-02-09Include qapi/qmp/qstring.h exactly where neededMarkus Armbruster
Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20180201111846.21846-14-armbru@redhat.com>
2018-02-09Include qapi/qmp/qdict.h exactly where neededMarkus Armbruster
This cleanup makes the number of objects depending on qapi/qmp/qdict.h drop from 4550 (out of 4743) to 368 in my "build everything" tree. For qapi/qmp/qobject.h, the number drops from 4552 to 390. While there, separate #include from file comment with a blank line. Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20180201111846.21846-13-armbru@redhat.com>
2018-02-09Include qapi/qmp/qlist.h exactly where neededMarkus Armbruster
This cleanup makes the number of objects depending on qapi/qmp/qlist.h drop from 4551 (out of 4743) to 16 in my "build everything" tree. While there, separate #include from file comment with a blank line. Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20180201111846.21846-12-armbru@redhat.com>
2018-02-09qdict qlist: Make most helper macros functionsMarkus Armbruster
The macro expansions of qdict_put_TYPE() and qlist_append_TYPE() need qbool.h, qnull.h, qnum.h and qstring.h to compile. We include qnull.h and qnum.h in the headers, but not qbool.h and qstring.h. Works, because we include those wherever the macros get used. Open-coding these helpers is of dubious value. Turn them into functions and drop the includes from the headers. This cleanup makes the number of objects depending on qapi/qmp/qnum.h from 4551 (out of 4743) to 46 in my "build everything" tree. For qapi/qmp/qnull.h, the number drops from 4552 to 21. Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20180201111846.21846-10-armbru@redhat.com>
2018-02-09Eliminate qapi/qmp/types.hMarkus Armbruster
qapi/qmp/types.h is a convenience header to include a number of qapi/qmp/ headers. Since we rarely need all of the headers qapi/qmp/types.h includes, we bypass it most of the time. Most of the places that use it don't need all the headers, either. Include the necessary headers directly, and drop qapi/qmp/types.h. Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20180201111846.21846-9-armbru@redhat.com>
2017-06-20qapi: merge QInt and QFloat in QNumMarc-André Lureau
We would like to use a same QObject type to represent numbers, whether they are int, uint, or floats. Getters will allow some compatibility between the various types if the number fits other representations. Add a few more tests while at it. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20170607163635.17635-7-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [parse_stats_intervals() simplified a bit, comment in test_visitor_in_int_overflow() tidied up, suppress bogus warnings] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2017-03-07qobject: Propagate parse errors through qobject_from_json()Markus Armbruster
The next few commits will put the errors to use where appropriate. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <1488317230-26248-13-git-send-email-armbru@redhat.com>
2017-03-07qjson: Abort earlier on qobject_from_jsonf() misuseMarkus Armbruster
Ignoring errors first, then asserting success is suboptimal. Pass &error_abort instead, so we abort earlier, and hopefully get more useful clues on what's wrong. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <1488317230-26248-11-git-send-email-armbru@redhat.com>
2017-03-07qobject: Propagate parse errors through qobject_from_jsonv()Markus Armbruster
The next few commits will put the errors to use where appropriate. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-Id: <1488317230-26248-9-git-send-email-armbru@redhat.com>
2016-07-06qapi: Improve use of qmp/types.hEric Blake
'qjson.h' is not a QObject subtype; include this file directly in .c files that are using it, rather than abusing qmp/types.h for that purpose. Meanwhile, for files that include a list of individual QObject subtypes, it's easier to just use qmp/types.h for that purpose. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1465490926-28625-2-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-22util: move declarations out of qemu-common.hVeronia Bahaa
Move declarations out of qemu-common.h for functions declared in utils/ files: e.g. include/qemu/path.h for utils/path.c. Move inline functions out of qemu-common.h and into new files (e.g. include/qemu/bcd.h) Signed-off-by: Veronia Bahaa <veroniabahaa@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-02-08qobject: Document more shortcomings in our number handlingEric Blake
We've already documented that our JSON parsing is locale dependent; but we should also document that our JSON output has the same problem. Additionally, JSON requires finite values (you have to upgrade to JSON5 to get support for Inf or NaN), and our output truncates floating point numbers to the point of losing significant precision that could cause the receiver to read a different value. Sadly, this series is not going to be the one that addresses these problems. Fix some trailing whitespace I noticed in the vicinity. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1454075341-13658-2-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-04qobject: Clean up includesPeter Maydell
Clean up includes so that osdep.h is included first and headers which it implies are not included manually. This commit was created with scripts/clean-includes. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 1454089805-5470-12-git-send-email-peter.maydell@linaro.org
2015-11-26qjson: store tokens in a GQueuePaolo Bonzini
Even though we still have the "streamer" concept, the tokens can now be deleted as they are read. While doing so convert from QList to GQueue, since the next step will make tokens not a QObject and we will have to do the conversion anyway. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <1448300659-23559-4-git-send-email-pbonzini@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-06-22qerror: Finally unused, clean upMarkus Armbruster
Remove it except for two things in qerror.h: * Two #include to be cleaned up separately to avoid cluttering this patch. * The QERR_ macros. Mark as obsolete. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-06-22qobject: Use 'bool' for qboolEric Blake
We require a C99 compiler, so let's use 'bool' instead of 'int' when dealing with boolean values. There are few enough clients to fix them all in one pass. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Andreas Färber <afaerber@suse.de> Reviewed-by: Alberto Garcia <berto@igalia.com> Acked-by: Luiz Capitulino <lcapitulino@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-05-11qobject: Add a special null QObjectMarkus Armbruster
I'm going to fix the JSON parser to recognize null. The obvious representation of JSON null as (QObject *)NULL doesn't work, because the parser already uses it as an error value. Perhaps we should change it to free NULL for null, but that's more than I can do right now. Create a special null QObject instead. The existing QDict, QList, and QString all represent something that is a pointer in C and could therefore be associated with NULL. But right now, all three of these sub-types are always non-null once created, so the new null sentinel object is intentionally unrelated to them. Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-05-11qobject: Clean up around qtype_codeMarkus Armbruster
QTYPE_NONE is a sentinel value. No QObject has this type code. Document it properly. Fix dump_qobject() to abort() on QTYPE_NONE, just like for any other invalid type code. Fix to_json() to abort() on all invalid type codes, not just QTYPE_MAX. Clean up Property member qtype's type: it's a qtype_code. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-12-10qjson: Drop trailing space for pretty formattingMax Reitz
For the pretty formatting, the functions converting QDicts and QLists to JSON should not print a space after the comma separating objects, because a newline will emitted immediately afterwards, making the whitespace superfluous. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2013-07-26qapi: Anonymous unionsKevin Wolf
The discriminator for anonymous unions is the data type. This allows to have a union type that allows both of these: { 'file': 'my_existing_block_device_id' } { 'file': { 'filename': '/tmp/mydisk.qcow2', 'read-only': true } } Unions like this are specified in the schema with an empty dict as discriminator. For this example you could take: { 'union': 'BlockRef', 'discriminator': {}, 'data': { 'definition': 'BlockOptions', 'reference': 'str' } } { 'type': 'ExampleObject', 'data: { 'file': 'BlockRef' } } Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2013-04-13qjson: to_json() case QTYPE_QSTRING is buggy, rewriteMarkus Armbruster
Known bugs in to_json(): * A start byte for a three-byte sequence followed by less than two continuation bytes is split into one-byte sequences. * Start bytes for sequences longer than three bytes get misinterpreted as start bytes for three-byte sequences. Continuation bytes beyond byte three become one-byte sequences. This means all characters outside the BMP are decoded incorrectly. * One-byte sequences with the MSB are put into the JSON string verbatim when char is unsigned, producing invalid UTF-8. When char is signed, they're replaced by "\\uFFFF" instead. This includes \xFE, \xFF, and stray continuation bytes. * Overlong sequences are happily accepted, unless screwed up by the bugs above. * Likewise, sequences encoding surrogate code points or noncharacters. * Unlike other control characters, ASCII DEL is not escaped. Except in overlong encodings. My rewrite fixes them as follows: * Malformed UTF-8 sequences are replaced. Except the overlong encoding \xC0\x80 of U+0000 is still accepted. Permits embedding NUL characters in C strings. This trick is known as "Modified UTF-8". * Sequences encoding code points beyond Unicode range are replaced. * Sequences encoding code points beyond the BMP produce a surrogate pair. * Sequences encoding surrogate code points are replaced. * Sequences encoding noncharacters are replaced. * ASCII DEL is now always escaped. The replacement character is U+FFFD. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2013-01-12build: move qobject files to qobject/ and libqemuutil.aPaolo Bonzini
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>