*
*/
-#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qdict.h"
-#include "qemu-common.h"
-#include "qapi/qmp/json-lexer.h"
-#include "qapi/qmp/json-streamer.h"
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "json-parser-int.h"
#define MAX_TOKEN_SIZE (64ULL << 20)
-#define MAX_NESTING (1ULL << 10)
+#define MAX_TOKEN_COUNT (2ULL << 20)
+#define MAX_NESTING (1 << 10)
-static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y)
+static void json_message_free_tokens(JSONMessageParser *parser)
+{
+ JSONToken *token;
+
+ while ((token = g_queue_pop_head(&parser->tokens))) {
+ g_free(token);
+ }
+}
+
+void json_message_process_token(JSONLexer *lexer, GString *input,
+ JSONTokenType type, int x, int y)
{
JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
- QDict *dict;
-
- if (type == JSON_OPERATOR) {
- switch (qstring_get_str(token)[0]) {
- case '{':
- parser->brace_count++;
- break;
- case '}':
- parser->brace_count--;
- break;
- case '[':
- parser->bracket_count++;
- break;
- case ']':
- parser->bracket_count--;
- break;
- default:
- break;
+ QObject *json = NULL;
+ Error *err = NULL;
+ JSONToken *token;
+
+ switch (type) {
+ case JSON_LCURLY:
+ parser->brace_count++;
+ break;
+ case JSON_RCURLY:
+ parser->brace_count--;
+ break;
+ case JSON_LSQUARE:
+ parser->bracket_count++;
+ break;
+ case JSON_RSQUARE:
+ parser->bracket_count--;
+ break;
+ case JSON_ERROR:
+ error_setg(&err, "JSON parse error, stray '%s'", input->str);
+ goto out_emit;
+ case JSON_END_OF_INPUT:
+ if (g_queue_is_empty(&parser->tokens)) {
+ return;
}
+ json = json_parser_parse(&parser->tokens, parser->ap, &err);
+ goto out_emit;
+ default:
+ break;
}
- dict = qdict_new();
- qdict_put(dict, "type", qint_from_int(type));
- QINCREF(token);
- qdict_put(dict, "token", token);
- qdict_put(dict, "x", qint_from_int(x));
- qdict_put(dict, "y", qint_from_int(y));
+ /*
+ * Security consideration, we limit total memory allocated per object
+ * and the maximum recursion depth that a message can force.
+ */
+ if (parser->token_size + input->len + 1 > MAX_TOKEN_SIZE) {
+ error_setg(&err, "JSON token size limit exceeded");
+ goto out_emit;
+ }
+ if (g_queue_get_length(&parser->tokens) + 1 > MAX_TOKEN_COUNT) {
+ error_setg(&err, "JSON token count limit exceeded");
+ goto out_emit;
+ }
+ if (parser->bracket_count + parser->brace_count > MAX_NESTING) {
+ error_setg(&err, "JSON nesting depth limit exceeded");
+ goto out_emit;
+ }
- parser->token_size += token->length;
+ token = json_token(type, x, y, input);
+ parser->token_size += input->len;
- qlist_append(parser->tokens, dict);
+ g_queue_push_tail(&parser->tokens, token);
- if (type == JSON_ERROR) {
- goto out_emit_bad;
- } else if (parser->brace_count < 0 ||
- parser->bracket_count < 0 ||
- (parser->brace_count == 0 &&
- parser->bracket_count == 0)) {
- goto out_emit;
- } else if (parser->token_size > MAX_TOKEN_SIZE ||
- parser->bracket_count + parser->brace_count > MAX_NESTING) {
- /* Security consideration, we limit total memory allocated per object
- * and the maximum recursion depth that a message can force.
- */
- goto out_emit;
+ if ((parser->brace_count > 0 || parser->bracket_count > 0)
+ && parser->bracket_count >= 0 && parser->bracket_count >= 0) {
+ return;
}
- return;
+ json = json_parser_parse(&parser->tokens, parser->ap, &err);
-out_emit_bad:
- /* clear out token list and tell the parser to emit and error
- * indication by passing it a NULL list
- */
- QDECREF(parser->tokens);
- parser->tokens = NULL;
out_emit:
- /* send current list of tokens to parser and reset tokenizer */
parser->brace_count = 0;
parser->bracket_count = 0;
- parser->emit(parser, parser->tokens);
- if (parser->tokens) {
- QDECREF(parser->tokens);
- }
- parser->tokens = qlist_new();
+ json_message_free_tokens(parser);
parser->token_size = 0;
+ parser->emit(parser->opaque, json, err);
}
void json_message_parser_init(JSONMessageParser *parser,
- void (*func)(JSONMessageParser *, QList *))
+ void (*emit)(void *opaque, QObject *json,
+ Error *err),
+ void *opaque, va_list *ap)
{
- parser->emit = func;
+ parser->emit = emit;
+ parser->opaque = opaque;
+ parser->ap = ap;
parser->brace_count = 0;
parser->bracket_count = 0;
- parser->tokens = qlist_new();
+ g_queue_init(&parser->tokens);
parser->token_size = 0;
- json_lexer_init(&parser->lexer, json_message_process_token);
+ json_lexer_init(&parser->lexer, !!ap);
}
-int json_message_parser_feed(JSONMessageParser *parser,
+void json_message_parser_feed(JSONMessageParser *parser,
const char *buffer, size_t size)
{
- return json_lexer_feed(&parser->lexer, buffer, size);
+ json_lexer_feed(&parser->lexer, buffer, size);
}
-int json_message_parser_flush(JSONMessageParser *parser)
+void json_message_parser_flush(JSONMessageParser *parser)
{
- return json_lexer_flush(&parser->lexer);
+ json_lexer_flush(&parser->lexer);
+ assert(g_queue_is_empty(&parser->tokens));
}
void json_message_parser_destroy(JSONMessageParser *parser)
{
json_lexer_destroy(&parser->lexer);
- QDECREF(parser->tokens);
+ json_message_free_tokens(parser);
}