2
0

json-streamer.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * JSON streaming support
  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. #include "qemu/osdep.h"
  14. #include "qemu-common.h"
  15. #include "qapi/qmp/json-lexer.h"
  16. #include "qapi/qmp/json-streamer.h"
  17. #define MAX_TOKEN_SIZE (64ULL << 20)
  18. #define MAX_TOKEN_COUNT (2ULL << 20)
  19. #define MAX_NESTING (1ULL << 10)
  20. static void json_message_free_token(void *token, void *opaque)
  21. {
  22. g_free(token);
  23. }
  24. static void json_message_free_tokens(JSONMessageParser *parser)
  25. {
  26. if (parser->tokens) {
  27. g_queue_foreach(parser->tokens, json_message_free_token, NULL);
  28. g_queue_free(parser->tokens);
  29. parser->tokens = NULL;
  30. }
  31. }
  32. static void json_message_process_token(JSONLexer *lexer, GString *input,
  33. JSONTokenType type, int x, int y)
  34. {
  35. JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
  36. JSONToken *token;
  37. GQueue *tokens;
  38. switch (type) {
  39. case JSON_LCURLY:
  40. parser->brace_count++;
  41. break;
  42. case JSON_RCURLY:
  43. parser->brace_count--;
  44. break;
  45. case JSON_LSQUARE:
  46. parser->bracket_count++;
  47. break;
  48. case JSON_RSQUARE:
  49. parser->bracket_count--;
  50. break;
  51. default:
  52. break;
  53. }
  54. token = g_malloc(sizeof(JSONToken) + input->len + 1);
  55. token->type = type;
  56. memcpy(token->str, input->str, input->len);
  57. token->str[input->len] = 0;
  58. token->x = x;
  59. token->y = y;
  60. parser->token_size += input->len;
  61. g_queue_push_tail(parser->tokens, token);
  62. if (type == JSON_ERROR) {
  63. goto out_emit_bad;
  64. } else if (parser->brace_count < 0 ||
  65. parser->bracket_count < 0 ||
  66. (parser->brace_count == 0 &&
  67. parser->bracket_count == 0)) {
  68. goto out_emit;
  69. } else if (parser->token_size > MAX_TOKEN_SIZE ||
  70. g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT ||
  71. parser->bracket_count + parser->brace_count > MAX_NESTING) {
  72. /* Security consideration, we limit total memory allocated per object
  73. * and the maximum recursion depth that a message can force.
  74. */
  75. goto out_emit_bad;
  76. }
  77. return;
  78. out_emit_bad:
  79. /*
  80. * Clear out token list and tell the parser to emit an error
  81. * indication by passing it a NULL list
  82. */
  83. json_message_free_tokens(parser);
  84. out_emit:
  85. /* send current list of tokens to parser and reset tokenizer */
  86. parser->brace_count = 0;
  87. parser->bracket_count = 0;
  88. /* parser->emit takes ownership of parser->tokens. Remove our own
  89. * reference to parser->tokens before handing it out to parser->emit.
  90. */
  91. tokens = parser->tokens;
  92. parser->tokens = g_queue_new();
  93. parser->emit(parser, tokens);
  94. parser->token_size = 0;
  95. }
  96. void json_message_parser_init(JSONMessageParser *parser,
  97. void (*func)(JSONMessageParser *, GQueue *))
  98. {
  99. parser->emit = func;
  100. parser->brace_count = 0;
  101. parser->bracket_count = 0;
  102. parser->tokens = g_queue_new();
  103. parser->token_size = 0;
  104. json_lexer_init(&parser->lexer, json_message_process_token);
  105. }
  106. int json_message_parser_feed(JSONMessageParser *parser,
  107. const char *buffer, size_t size)
  108. {
  109. return json_lexer_feed(&parser->lexer, buffer, size);
  110. }
  111. int json_message_parser_flush(JSONMessageParser *parser)
  112. {
  113. return json_lexer_flush(&parser->lexer);
  114. }
  115. void json_message_parser_destroy(JSONMessageParser *parser)
  116. {
  117. json_lexer_destroy(&parser->lexer);
  118. json_message_free_tokens(parser);
  119. }