json-parser.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /*
  2. * JSON Parser
  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 "qapi/error.h"
  15. #include "qemu-common.h"
  16. #include "qapi/qmp/types.h"
  17. #include "qapi/qmp/json-parser.h"
  18. #include "qapi/qmp/json-lexer.h"
  19. #include "qapi/qmp/json-streamer.h"
  20. typedef struct JSONParserContext
  21. {
  22. Error *err;
  23. JSONToken *current;
  24. GQueue *buf;
  25. } JSONParserContext;
  26. #define BUG_ON(cond) assert(!(cond))
  27. /**
  28. * TODO
  29. *
  30. * 0) make errors meaningful again
  31. * 1) add geometry information to tokens
  32. * 3) should we return a parsed size?
  33. * 4) deal with premature EOI
  34. */
  35. static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
  36. /**
  37. * Error handler
  38. */
  39. static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt,
  40. JSONToken *token, const char *msg, ...)
  41. {
  42. va_list ap;
  43. char message[1024];
  44. va_start(ap, msg);
  45. vsnprintf(message, sizeof(message), msg, ap);
  46. va_end(ap);
  47. if (ctxt->err) {
  48. error_free(ctxt->err);
  49. ctxt->err = NULL;
  50. }
  51. error_setg(&ctxt->err, "JSON parse error, %s", message);
  52. }
  53. /**
  54. * String helpers
  55. *
  56. * These helpers are used to unescape strings.
  57. */
  58. static void wchar_to_utf8(uint16_t wchar, char *buffer, size_t buffer_length)
  59. {
  60. if (wchar <= 0x007F) {
  61. BUG_ON(buffer_length < 2);
  62. buffer[0] = wchar & 0x7F;
  63. buffer[1] = 0;
  64. } else if (wchar <= 0x07FF) {
  65. BUG_ON(buffer_length < 3);
  66. buffer[0] = 0xC0 | ((wchar >> 6) & 0x1F);
  67. buffer[1] = 0x80 | (wchar & 0x3F);
  68. buffer[2] = 0;
  69. } else {
  70. BUG_ON(buffer_length < 4);
  71. buffer[0] = 0xE0 | ((wchar >> 12) & 0x0F);
  72. buffer[1] = 0x80 | ((wchar >> 6) & 0x3F);
  73. buffer[2] = 0x80 | (wchar & 0x3F);
  74. buffer[3] = 0;
  75. }
  76. }
  77. static int hex2decimal(char ch)
  78. {
  79. if (ch >= '0' && ch <= '9') {
  80. return (ch - '0');
  81. } else if (ch >= 'a' && ch <= 'f') {
  82. return 10 + (ch - 'a');
  83. } else if (ch >= 'A' && ch <= 'F') {
  84. return 10 + (ch - 'A');
  85. }
  86. return -1;
  87. }
  88. /**
  89. * parse_string(): Parse a json string and return a QObject
  90. *
  91. * string
  92. * ""
  93. * " chars "
  94. * chars
  95. * char
  96. * char chars
  97. * char
  98. * any-Unicode-character-
  99. * except-"-or-\-or-
  100. * control-character
  101. * \"
  102. * \\
  103. * \/
  104. * \b
  105. * \f
  106. * \n
  107. * \r
  108. * \t
  109. * \u four-hex-digits
  110. */
  111. static QString *qstring_from_escaped_str(JSONParserContext *ctxt,
  112. JSONToken *token)
  113. {
  114. const char *ptr = token->str;
  115. QString *str;
  116. int double_quote = 1;
  117. if (*ptr == '"') {
  118. double_quote = 1;
  119. } else {
  120. double_quote = 0;
  121. }
  122. ptr++;
  123. str = qstring_new();
  124. while (*ptr &&
  125. ((double_quote && *ptr != '"') || (!double_quote && *ptr != '\''))) {
  126. if (*ptr == '\\') {
  127. ptr++;
  128. switch (*ptr) {
  129. case '"':
  130. qstring_append(str, "\"");
  131. ptr++;
  132. break;
  133. case '\'':
  134. qstring_append(str, "'");
  135. ptr++;
  136. break;
  137. case '\\':
  138. qstring_append(str, "\\");
  139. ptr++;
  140. break;
  141. case '/':
  142. qstring_append(str, "/");
  143. ptr++;
  144. break;
  145. case 'b':
  146. qstring_append(str, "\b");
  147. ptr++;
  148. break;
  149. case 'f':
  150. qstring_append(str, "\f");
  151. ptr++;
  152. break;
  153. case 'n':
  154. qstring_append(str, "\n");
  155. ptr++;
  156. break;
  157. case 'r':
  158. qstring_append(str, "\r");
  159. ptr++;
  160. break;
  161. case 't':
  162. qstring_append(str, "\t");
  163. ptr++;
  164. break;
  165. case 'u': {
  166. uint16_t unicode_char = 0;
  167. char utf8_char[4];
  168. int i = 0;
  169. ptr++;
  170. for (i = 0; i < 4; i++) {
  171. if (qemu_isxdigit(*ptr)) {
  172. unicode_char |= hex2decimal(*ptr) << ((3 - i) * 4);
  173. } else {
  174. parse_error(ctxt, token,
  175. "invalid hex escape sequence in string");
  176. goto out;
  177. }
  178. ptr++;
  179. }
  180. wchar_to_utf8(unicode_char, utf8_char, sizeof(utf8_char));
  181. qstring_append(str, utf8_char);
  182. } break;
  183. default:
  184. parse_error(ctxt, token, "invalid escape sequence in string");
  185. goto out;
  186. }
  187. } else {
  188. char dummy[2];
  189. dummy[0] = *ptr++;
  190. dummy[1] = 0;
  191. qstring_append(str, dummy);
  192. }
  193. }
  194. return str;
  195. out:
  196. QDECREF(str);
  197. return NULL;
  198. }
  199. /* Note: the token object returned by parser_context_peek_token or
  200. * parser_context_pop_token is deleted as soon as parser_context_pop_token
  201. * is called again.
  202. */
  203. static JSONToken *parser_context_pop_token(JSONParserContext *ctxt)
  204. {
  205. g_free(ctxt->current);
  206. assert(!g_queue_is_empty(ctxt->buf));
  207. ctxt->current = g_queue_pop_head(ctxt->buf);
  208. return ctxt->current;
  209. }
  210. static JSONToken *parser_context_peek_token(JSONParserContext *ctxt)
  211. {
  212. assert(!g_queue_is_empty(ctxt->buf));
  213. return g_queue_peek_head(ctxt->buf);
  214. }
  215. static JSONParserContext *parser_context_new(GQueue *tokens)
  216. {
  217. JSONParserContext *ctxt;
  218. if (!tokens) {
  219. return NULL;
  220. }
  221. ctxt = g_malloc0(sizeof(JSONParserContext));
  222. ctxt->buf = tokens;
  223. return ctxt;
  224. }
  225. /* to support error propagation, ctxt->err must be freed separately */
  226. static void parser_context_free(JSONParserContext *ctxt)
  227. {
  228. if (ctxt) {
  229. while (!g_queue_is_empty(ctxt->buf)) {
  230. parser_context_pop_token(ctxt);
  231. }
  232. g_free(ctxt->current);
  233. g_queue_free(ctxt->buf);
  234. g_free(ctxt);
  235. }
  236. }
  237. /**
  238. * Parsing rules
  239. */
  240. static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
  241. {
  242. QObject *key = NULL, *value;
  243. JSONToken *peek, *token;
  244. peek = parser_context_peek_token(ctxt);
  245. if (peek == NULL) {
  246. parse_error(ctxt, NULL, "premature EOI");
  247. goto out;
  248. }
  249. key = parse_value(ctxt, ap);
  250. if (!key || qobject_type(key) != QTYPE_QSTRING) {
  251. parse_error(ctxt, peek, "key is not a string in object");
  252. goto out;
  253. }
  254. token = parser_context_pop_token(ctxt);
  255. if (token == NULL) {
  256. parse_error(ctxt, NULL, "premature EOI");
  257. goto out;
  258. }
  259. if (token->type != JSON_COLON) {
  260. parse_error(ctxt, token, "missing : in object pair");
  261. goto out;
  262. }
  263. value = parse_value(ctxt, ap);
  264. if (value == NULL) {
  265. parse_error(ctxt, token, "Missing value in dict");
  266. goto out;
  267. }
  268. qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value);
  269. qobject_decref(key);
  270. return 0;
  271. out:
  272. qobject_decref(key);
  273. return -1;
  274. }
  275. static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
  276. {
  277. QDict *dict = NULL;
  278. JSONToken *token, *peek;
  279. token = parser_context_pop_token(ctxt);
  280. assert(token && token->type == JSON_LCURLY);
  281. dict = qdict_new();
  282. peek = parser_context_peek_token(ctxt);
  283. if (peek == NULL) {
  284. parse_error(ctxt, NULL, "premature EOI");
  285. goto out;
  286. }
  287. if (peek->type != JSON_RCURLY) {
  288. if (parse_pair(ctxt, dict, ap) == -1) {
  289. goto out;
  290. }
  291. token = parser_context_pop_token(ctxt);
  292. if (token == NULL) {
  293. parse_error(ctxt, NULL, "premature EOI");
  294. goto out;
  295. }
  296. while (token->type != JSON_RCURLY) {
  297. if (token->type != JSON_COMMA) {
  298. parse_error(ctxt, token, "expected separator in dict");
  299. goto out;
  300. }
  301. if (parse_pair(ctxt, dict, ap) == -1) {
  302. goto out;
  303. }
  304. token = parser_context_pop_token(ctxt);
  305. if (token == NULL) {
  306. parse_error(ctxt, NULL, "premature EOI");
  307. goto out;
  308. }
  309. }
  310. } else {
  311. (void)parser_context_pop_token(ctxt);
  312. }
  313. return QOBJECT(dict);
  314. out:
  315. QDECREF(dict);
  316. return NULL;
  317. }
  318. static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
  319. {
  320. QList *list = NULL;
  321. JSONToken *token, *peek;
  322. token = parser_context_pop_token(ctxt);
  323. assert(token && token->type == JSON_LSQUARE);
  324. list = qlist_new();
  325. peek = parser_context_peek_token(ctxt);
  326. if (peek == NULL) {
  327. parse_error(ctxt, NULL, "premature EOI");
  328. goto out;
  329. }
  330. if (peek->type != JSON_RSQUARE) {
  331. QObject *obj;
  332. obj = parse_value(ctxt, ap);
  333. if (obj == NULL) {
  334. parse_error(ctxt, token, "expecting value");
  335. goto out;
  336. }
  337. qlist_append_obj(list, obj);
  338. token = parser_context_pop_token(ctxt);
  339. if (token == NULL) {
  340. parse_error(ctxt, NULL, "premature EOI");
  341. goto out;
  342. }
  343. while (token->type != JSON_RSQUARE) {
  344. if (token->type != JSON_COMMA) {
  345. parse_error(ctxt, token, "expected separator in list");
  346. goto out;
  347. }
  348. obj = parse_value(ctxt, ap);
  349. if (obj == NULL) {
  350. parse_error(ctxt, token, "expecting value");
  351. goto out;
  352. }
  353. qlist_append_obj(list, obj);
  354. token = parser_context_pop_token(ctxt);
  355. if (token == NULL) {
  356. parse_error(ctxt, NULL, "premature EOI");
  357. goto out;
  358. }
  359. }
  360. } else {
  361. (void)parser_context_pop_token(ctxt);
  362. }
  363. return QOBJECT(list);
  364. out:
  365. QDECREF(list);
  366. return NULL;
  367. }
  368. static QObject *parse_keyword(JSONParserContext *ctxt)
  369. {
  370. JSONToken *token;
  371. token = parser_context_pop_token(ctxt);
  372. assert(token && token->type == JSON_KEYWORD);
  373. if (!strcmp(token->str, "true")) {
  374. return QOBJECT(qbool_from_bool(true));
  375. } else if (!strcmp(token->str, "false")) {
  376. return QOBJECT(qbool_from_bool(false));
  377. } else if (!strcmp(token->str, "null")) {
  378. return qnull();
  379. }
  380. parse_error(ctxt, token, "invalid keyword '%s'", token->str);
  381. return NULL;
  382. }
  383. static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
  384. {
  385. JSONToken *token;
  386. if (ap == NULL) {
  387. return NULL;
  388. }
  389. token = parser_context_pop_token(ctxt);
  390. assert(token && token->type == JSON_ESCAPE);
  391. if (!strcmp(token->str, "%p")) {
  392. return va_arg(*ap, QObject *);
  393. } else if (!strcmp(token->str, "%i")) {
  394. return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
  395. } else if (!strcmp(token->str, "%d")) {
  396. return QOBJECT(qint_from_int(va_arg(*ap, int)));
  397. } else if (!strcmp(token->str, "%ld")) {
  398. return QOBJECT(qint_from_int(va_arg(*ap, long)));
  399. } else if (!strcmp(token->str, "%lld") ||
  400. !strcmp(token->str, "%I64d")) {
  401. return QOBJECT(qint_from_int(va_arg(*ap, long long)));
  402. } else if (!strcmp(token->str, "%s")) {
  403. return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
  404. } else if (!strcmp(token->str, "%f")) {
  405. return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
  406. }
  407. return NULL;
  408. }
  409. static QObject *parse_literal(JSONParserContext *ctxt)
  410. {
  411. JSONToken *token;
  412. token = parser_context_pop_token(ctxt);
  413. assert(token);
  414. switch (token->type) {
  415. case JSON_STRING:
  416. return QOBJECT(qstring_from_escaped_str(ctxt, token));
  417. case JSON_INTEGER: {
  418. /* A possibility exists that this is a whole-valued float where the
  419. * fractional part was left out due to being 0 (.0). It's not a big
  420. * deal to treat these as ints in the parser, so long as users of the
  421. * resulting QObject know to expect a QInt in place of a QFloat in
  422. * cases like these.
  423. *
  424. * However, in some cases these values will overflow/underflow a
  425. * QInt/int64 container, thus we should assume these are to be handled
  426. * as QFloats/doubles rather than silently changing their values.
  427. *
  428. * strtoll() indicates these instances by setting errno to ERANGE
  429. */
  430. int64_t value;
  431. errno = 0; /* strtoll doesn't set errno on success */
  432. value = strtoll(token->str, NULL, 10);
  433. if (errno != ERANGE) {
  434. return QOBJECT(qint_from_int(value));
  435. }
  436. /* fall through to JSON_FLOAT */
  437. }
  438. case JSON_FLOAT:
  439. /* FIXME dependent on locale; a pervasive issue in QEMU */
  440. /* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN,
  441. * but those might be useful extensions beyond JSON */
  442. return QOBJECT(qfloat_from_double(strtod(token->str, NULL)));
  443. default:
  444. abort();
  445. }
  446. }
  447. static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
  448. {
  449. JSONToken *token;
  450. token = parser_context_peek_token(ctxt);
  451. if (token == NULL) {
  452. parse_error(ctxt, NULL, "premature EOI");
  453. return NULL;
  454. }
  455. switch (token->type) {
  456. case JSON_LCURLY:
  457. return parse_object(ctxt, ap);
  458. case JSON_LSQUARE:
  459. return parse_array(ctxt, ap);
  460. case JSON_ESCAPE:
  461. return parse_escape(ctxt, ap);
  462. case JSON_INTEGER:
  463. case JSON_FLOAT:
  464. case JSON_STRING:
  465. return parse_literal(ctxt);
  466. case JSON_KEYWORD:
  467. return parse_keyword(ctxt);
  468. default:
  469. parse_error(ctxt, token, "expecting value");
  470. return NULL;
  471. }
  472. }
  473. QObject *json_parser_parse(GQueue *tokens, va_list *ap)
  474. {
  475. return json_parser_parse_err(tokens, ap, NULL);
  476. }
  477. QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
  478. {
  479. JSONParserContext *ctxt = parser_context_new(tokens);
  480. QObject *result;
  481. if (!ctxt) {
  482. return NULL;
  483. }
  484. result = parse_value(ctxt, ap);
  485. error_propagate(errp, ctxt->err);
  486. parser_context_free(ctxt);
  487. return result;
  488. }