cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qjson.c (5848B)


      1/*
      2 * QObject JSON integration
      3 *
      4 * Copyright IBM, Corp. 2009
      5 *
      6 * Authors:
      7 *  Anthony Liguori   <aliguori@us.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
     10 * See the COPYING.LIB file in the top-level directory.
     11 *
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "qapi/error.h"
     16#include "qapi/qmp/json-parser.h"
     17#include "qapi/qmp/json-writer.h"
     18#include "qapi/qmp/qjson.h"
     19#include "qapi/qmp/qbool.h"
     20#include "qapi/qmp/qdict.h"
     21#include "qapi/qmp/qlist.h"
     22#include "qapi/qmp/qnum.h"
     23#include "qapi/qmp/qstring.h"
     24
     25typedef struct JSONParsingState {
     26    JSONMessageParser parser;
     27    QObject *result;
     28    Error *err;
     29} JSONParsingState;
     30
     31static void consume_json(void *opaque, QObject *json, Error *err)
     32{
     33    JSONParsingState *s = opaque;
     34
     35    assert(!json != !err);
     36    assert(!s->result || !s->err);
     37
     38    if (s->result) {
     39        qobject_unref(s->result);
     40        s->result = NULL;
     41        error_setg(&s->err, "Expecting at most one JSON value");
     42    }
     43    if (s->err) {
     44        qobject_unref(json);
     45        error_free(err);
     46        return;
     47    }
     48    s->result = json;
     49    s->err = err;
     50}
     51
     52/*
     53 * Parse @string as JSON value.
     54 * If @ap is non-null, interpolate %-escapes.
     55 * Takes ownership of %p arguments.
     56 * On success, return the JSON value.
     57 * On failure, store an error through @errp and return NULL.
     58 * Ownership of %p arguments becomes indeterminate then.  To avoid
     59 * leaks, callers passing %p must terminate on error, e.g. by passing
     60 * &error_abort.
     61 */
     62static QObject *qobject_from_jsonv(const char *string, va_list *ap,
     63                                   Error **errp)
     64{
     65    JSONParsingState state = {};
     66
     67    json_message_parser_init(&state.parser, consume_json, &state, ap);
     68    json_message_parser_feed(&state.parser, string, strlen(string));
     69    json_message_parser_flush(&state.parser);
     70    json_message_parser_destroy(&state.parser);
     71
     72    if (!state.result && !state.err) {
     73        error_setg(&state.err, "Expecting a JSON value");
     74    }
     75
     76    error_propagate(errp, state.err);
     77    return state.result;
     78}
     79
     80QObject *qobject_from_json(const char *string, Error **errp)
     81{
     82    return qobject_from_jsonv(string, NULL, errp);
     83}
     84
     85/*
     86 * Parse @string as JSON value with %-escapes interpolated.
     87 * Abort on error.  Do not use with untrusted @string.
     88 * Return the resulting QObject.  It is never null.
     89 */
     90QObject *qobject_from_vjsonf_nofail(const char *string, va_list ap)
     91{
     92    va_list ap_copy;
     93    QObject *obj;
     94
     95    /* va_copy() is needed when va_list is an array type */
     96    va_copy(ap_copy, ap);
     97    obj = qobject_from_jsonv(string, &ap_copy, &error_abort);
     98    va_end(ap_copy);
     99
    100    assert(obj);
    101    return obj;
    102}
    103
    104/*
    105 * Parse @string as JSON value with %-escapes interpolated.
    106 * Abort on error.  Do not use with untrusted @string.
    107 * Return the resulting QObject.  It is never null.
    108 */
    109QObject *qobject_from_jsonf_nofail(const char *string, ...)
    110{
    111    QObject *obj;
    112    va_list ap;
    113
    114    va_start(ap, string);
    115    obj = qobject_from_vjsonf_nofail(string, ap);
    116    va_end(ap);
    117
    118    return obj;
    119}
    120
    121/*
    122 * Parse @string as JSON object with %-escapes interpolated.
    123 * Abort on error.  Do not use with untrusted @string.
    124 * Return the resulting QDict.  It is never null.
    125 */
    126QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
    127{
    128    QDict *qdict;
    129
    130    qdict = qobject_to(QDict, qobject_from_vjsonf_nofail(string, ap));
    131    assert(qdict);
    132    return qdict;
    133}
    134
    135/*
    136 * Parse @string as JSON object with %-escapes interpolated.
    137 * Abort on error.  Do not use with untrusted @string.
    138 * Return the resulting QDict.  It is never null.
    139 */
    140QDict *qdict_from_jsonf_nofail(const char *string, ...)
    141{
    142    QDict *qdict;
    143    va_list ap;
    144
    145    va_start(ap, string);
    146    qdict = qdict_from_vjsonf_nofail(string, ap);
    147    va_end(ap);
    148    return qdict;
    149}
    150
    151static void to_json(JSONWriter *writer, const char *name,
    152                    const QObject *obj)
    153{
    154    switch (qobject_type(obj)) {
    155    case QTYPE_QNULL:
    156        json_writer_null(writer, name);
    157        break;
    158    case QTYPE_QNUM: {
    159        QNum *val = qobject_to(QNum, obj);
    160
    161        switch (val->kind) {
    162        case QNUM_I64:
    163            json_writer_int64(writer, name, val->u.i64);
    164            break;
    165        case QNUM_U64:
    166            json_writer_uint64(writer, name, val->u.u64);
    167            break;
    168        case QNUM_DOUBLE:
    169            json_writer_double(writer, name, val->u.dbl);
    170            break;
    171        default:
    172            abort();
    173        }
    174        break;
    175    }
    176    case QTYPE_QSTRING: {
    177        QString *val = qobject_to(QString, obj);
    178
    179        json_writer_str(writer, name, qstring_get_str(val));
    180        break;
    181    }
    182    case QTYPE_QDICT: {
    183        QDict *val = qobject_to(QDict, obj);
    184        const QDictEntry *entry;
    185
    186        json_writer_start_object(writer, name);
    187
    188        for (entry = qdict_first(val);
    189             entry;
    190             entry = qdict_next(val, entry)) {
    191            to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
    192        }
    193
    194        json_writer_end_object(writer);
    195        break;
    196    }
    197    case QTYPE_QLIST: {
    198        QList *val = qobject_to(QList, obj);
    199        QListEntry *entry;
    200
    201        json_writer_start_array(writer, name);
    202
    203        QLIST_FOREACH_ENTRY(val, entry) {
    204            to_json(writer, NULL, qlist_entry_obj(entry));
    205        }
    206
    207        json_writer_end_array(writer);
    208        break;
    209    }
    210    case QTYPE_QBOOL: {
    211        QBool *val = qobject_to(QBool, obj);
    212
    213        json_writer_bool(writer, name, qbool_get_bool(val));
    214        break;
    215    }
    216    default:
    217        abort();
    218    }
    219}
    220
    221GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
    222{
    223    JSONWriter *writer = json_writer_new(pretty);
    224
    225    to_json(writer, NULL, obj);
    226    return json_writer_get_and_free(writer);
    227}
    228
    229GString *qobject_to_json(const QObject *obj)
    230{
    231    return qobject_to_json_pretty(obj, false);
    232}