xref: /openbmc/qemu/qobject/json-streamer.c (revision 3f0fb073792180ccb1646d662e2d13260f2dd984)
1a372823aSPaolo Bonzini /*
2a372823aSPaolo Bonzini  * JSON streaming support
3a372823aSPaolo Bonzini  *
4a372823aSPaolo Bonzini  * Copyright IBM, Corp. 2009
5a372823aSPaolo Bonzini  *
6a372823aSPaolo Bonzini  * Authors:
7a372823aSPaolo Bonzini  *  Anthony Liguori   <aliguori@us.ibm.com>
8a372823aSPaolo Bonzini  *
9a372823aSPaolo Bonzini  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10a372823aSPaolo Bonzini  * See the COPYING.LIB file in the top-level directory.
11a372823aSPaolo Bonzini  *
12a372823aSPaolo Bonzini  */
13a372823aSPaolo Bonzini 
14f2ad72b3SPeter Maydell #include "qemu/osdep.h"
1584a56f38SMarkus Armbruster #include "qapi/error.h"
1686cdf9ecSMarkus Armbruster #include "json-parser-int.h"
17a372823aSPaolo Bonzini 
18a372823aSPaolo Bonzini #define MAX_TOKEN_SIZE (64ULL << 20)
19df649835SMarkus Armbruster #define MAX_TOKEN_COUNT (2ULL << 20)
20da09cfbfSMarkus Armbruster #define MAX_NESTING (1 << 10)
21a372823aSPaolo Bonzini 
json_message_free_tokens(JSONMessageParser * parser)2295385fe9SPaolo Bonzini static void json_message_free_tokens(JSONMessageParser *parser)
2395385fe9SPaolo Bonzini {
24a2731e08SMarkus Armbruster     JSONToken *token;
25a2731e08SMarkus Armbruster 
26a2731e08SMarkus Armbruster     while ((token = g_queue_pop_head(&parser->tokens))) {
27a2731e08SMarkus Armbruster         g_free(token);
2895385fe9SPaolo Bonzini     }
2995385fe9SPaolo Bonzini }
3095385fe9SPaolo Bonzini 
json_message_process_token(JSONLexer * lexer,GString * input,JSONTokenType type,int x,int y)31037f2440SMarkus Armbruster void json_message_process_token(JSONLexer *lexer, GString *input,
32d2ca7c0bSPaolo Bonzini                                 JSONTokenType type, int x, int y)
33a372823aSPaolo Bonzini {
34a372823aSPaolo Bonzini     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
35ff281a27SMarkus Armbruster     QObject *json = NULL;
3662815d85SMarkus Armbruster     Error *err = NULL;
379bada897SPaolo Bonzini     JSONToken *token;
38a372823aSPaolo Bonzini 
39c5461660SMarkus Armbruster     switch (type) {
40c5461660SMarkus Armbruster     case JSON_LCURLY:
41a372823aSPaolo Bonzini         parser->brace_count++;
42a372823aSPaolo Bonzini         break;
43c5461660SMarkus Armbruster     case JSON_RCURLY:
44a372823aSPaolo Bonzini         parser->brace_count--;
45a372823aSPaolo Bonzini         break;
46c5461660SMarkus Armbruster     case JSON_LSQUARE:
47a372823aSPaolo Bonzini         parser->bracket_count++;
48a372823aSPaolo Bonzini         break;
49c5461660SMarkus Armbruster     case JSON_RSQUARE:
50a372823aSPaolo Bonzini         parser->bracket_count--;
51a372823aSPaolo Bonzini         break;
52269e57aeSMarkus Armbruster     case JSON_ERROR:
5384a56f38SMarkus Armbruster         error_setg(&err, "JSON parse error, stray '%s'", input->str);
54269e57aeSMarkus Armbruster         goto out_emit;
55f9277915SMarkus Armbruster     case JSON_END_OF_INPUT:
56a2731e08SMarkus Armbruster         if (g_queue_is_empty(&parser->tokens)) {
57f9277915SMarkus Armbruster             return;
58f9277915SMarkus Armbruster         }
59a2731e08SMarkus Armbruster         json = json_parser_parse(&parser->tokens, parser->ap, &err);
60f9277915SMarkus Armbruster         goto out_emit;
61a372823aSPaolo Bonzini     default:
62a372823aSPaolo Bonzini         break;
63a372823aSPaolo Bonzini     }
64a372823aSPaolo Bonzini 
65da09cfbfSMarkus Armbruster     /*
66da09cfbfSMarkus Armbruster      * Security consideration, we limit total memory allocated per object
67da09cfbfSMarkus Armbruster      * and the maximum recursion depth that a message can force.
68da09cfbfSMarkus Armbruster      */
69da09cfbfSMarkus Armbruster     if (parser->token_size + input->len + 1 > MAX_TOKEN_SIZE) {
70da09cfbfSMarkus Armbruster         error_setg(&err, "JSON token size limit exceeded");
71da09cfbfSMarkus Armbruster         goto out_emit;
72da09cfbfSMarkus Armbruster     }
73a2731e08SMarkus Armbruster     if (g_queue_get_length(&parser->tokens) + 1 > MAX_TOKEN_COUNT) {
74da09cfbfSMarkus Armbruster         error_setg(&err, "JSON token count limit exceeded");
75da09cfbfSMarkus Armbruster         goto out_emit;
76da09cfbfSMarkus Armbruster     }
77da09cfbfSMarkus Armbruster     if (parser->bracket_count + parser->brace_count > MAX_NESTING) {
78da09cfbfSMarkus Armbruster         error_setg(&err, "JSON nesting depth limit exceeded");
79da09cfbfSMarkus Armbruster         goto out_emit;
80da09cfbfSMarkus Armbruster     }
81da09cfbfSMarkus Armbruster 
82abe7c206SMarkus Armbruster     token = json_token(type, x, y, input);
83d2ca7c0bSPaolo Bonzini     parser->token_size += input->len;
84a372823aSPaolo Bonzini 
85a2731e08SMarkus Armbruster     g_queue_push_tail(&parser->tokens, token);
86a372823aSPaolo Bonzini 
878d3265b3SMarkus Armbruster     if ((parser->brace_count > 0 || parser->bracket_count > 0)
88*1394dc06SSimran Singhal         && parser->brace_count >= 0 && parser->bracket_count >= 0) {
898d3265b3SMarkus Armbruster         return;
90ff281a27SMarkus Armbruster     }
91ff281a27SMarkus Armbruster 
92a2731e08SMarkus Armbruster     json = json_parser_parse(&parser->tokens, parser->ap, &err);
93a372823aSPaolo Bonzini 
94a372823aSPaolo Bonzini out_emit:
95a372823aSPaolo Bonzini     parser->brace_count = 0;
96a372823aSPaolo Bonzini     parser->bracket_count = 0;
97ff281a27SMarkus Armbruster     json_message_free_tokens(parser);
98a372823aSPaolo Bonzini     parser->token_size = 0;
9962815d85SMarkus Armbruster     parser->emit(parser->opaque, json, err);
100a372823aSPaolo Bonzini }
101a372823aSPaolo Bonzini 
json_message_parser_init(JSONMessageParser * parser,void (* emit)(void * opaque,QObject * json,Error * err),void * opaque,va_list * ap)102a372823aSPaolo Bonzini void json_message_parser_init(JSONMessageParser *parser,
10362815d85SMarkus Armbruster                               void (*emit)(void *opaque, QObject *json,
10462815d85SMarkus Armbruster                                            Error *err),
10562815d85SMarkus Armbruster                               void *opaque, va_list *ap)
106a372823aSPaolo Bonzini {
10762815d85SMarkus Armbruster     parser->emit = emit;
10862815d85SMarkus Armbruster     parser->opaque = opaque;
10962815d85SMarkus Armbruster     parser->ap = ap;
110a372823aSPaolo Bonzini     parser->brace_count = 0;
111a372823aSPaolo Bonzini     parser->bracket_count = 0;
112a2731e08SMarkus Armbruster     g_queue_init(&parser->tokens);
113a372823aSPaolo Bonzini     parser->token_size = 0;
114a372823aSPaolo Bonzini 
1152cbd15aaSMarkus Armbruster     json_lexer_init(&parser->lexer, !!ap);
116a372823aSPaolo Bonzini }
117a372823aSPaolo Bonzini 
json_message_parser_feed(JSONMessageParser * parser,const char * buffer,size_t size)1187c1e1d54SMarc-André Lureau void json_message_parser_feed(JSONMessageParser *parser,
119a372823aSPaolo Bonzini                              const char *buffer, size_t size)
120a372823aSPaolo Bonzini {
1217c1e1d54SMarc-André Lureau     json_lexer_feed(&parser->lexer, buffer, size);
122a372823aSPaolo Bonzini }
123a372823aSPaolo Bonzini 
json_message_parser_flush(JSONMessageParser * parser)1247c1e1d54SMarc-André Lureau void json_message_parser_flush(JSONMessageParser *parser)
125a372823aSPaolo Bonzini {
1267c1e1d54SMarc-André Lureau     json_lexer_flush(&parser->lexer);
127a2731e08SMarkus Armbruster     assert(g_queue_is_empty(&parser->tokens));
128a372823aSPaolo Bonzini }
129a372823aSPaolo Bonzini 
json_message_parser_destroy(JSONMessageParser * parser)130a372823aSPaolo Bonzini void json_message_parser_destroy(JSONMessageParser *parser)
131a372823aSPaolo Bonzini {
132a372823aSPaolo Bonzini     json_lexer_destroy(&parser->lexer);
13395385fe9SPaolo Bonzini     json_message_free_tokens(parser);
134a372823aSPaolo Bonzini }
135