json-parser.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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 "qemu/cutils.h"
  15. #include "qemu/unicode.h"
  16. #include "qapi/error.h"
  17. #include "qemu-common.h"
  18. #include "qapi/qmp/qbool.h"
  19. #include "qapi/qmp/qdict.h"
  20. #include "qapi/qmp/qlist.h"
  21. #include "qapi/qmp/qnull.h"
  22. #include "qapi/qmp/qnum.h"
  23. #include "qapi/qmp/qstring.h"
  24. #include "qapi/qmp/json-parser.h"
  25. #include "qapi/qmp/json-lexer.h"
  26. #include "qapi/qmp/json-streamer.h"
  27. typedef struct JSONParserContext
  28. {
  29. Error *err;
  30. JSONToken *current;
  31. GQueue *buf;
  32. } JSONParserContext;
  33. #define BUG_ON(cond) assert(!(cond))
  34. /**
  35. * TODO
  36. *
  37. * 0) make errors meaningful again
  38. * 1) add geometry information to tokens
  39. * 3) should we return a parsed size?
  40. * 4) deal with premature EOI
  41. */
  42. static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
  43. /**
  44. * Error handler
  45. */
  46. static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt,
  47. JSONToken *token, const char *msg, ...)
  48. {
  49. va_list ap;
  50. char message[1024];
  51. if (ctxt->err) {
  52. return;
  53. }
  54. va_start(ap, msg);
  55. vsnprintf(message, sizeof(message), msg, ap);
  56. va_end(ap);
  57. error_setg(&ctxt->err, "JSON parse error, %s", message);
  58. }
  59. /**
  60. * String helpers
  61. *
  62. * These helpers are used to unescape strings.
  63. */
  64. static void wchar_to_utf8(uint16_t wchar, char *buffer, size_t buffer_length)
  65. {
  66. if (wchar <= 0x007F) {
  67. BUG_ON(buffer_length < 2);
  68. buffer[0] = wchar & 0x7F;
  69. buffer[1] = 0;
  70. } else if (wchar <= 0x07FF) {
  71. BUG_ON(buffer_length < 3);
  72. buffer[0] = 0xC0 | ((wchar >> 6) & 0x1F);
  73. buffer[1] = 0x80 | (wchar & 0x3F);
  74. buffer[2] = 0;
  75. } else {
  76. BUG_ON(buffer_length < 4);
  77. buffer[0] = 0xE0 | ((wchar >> 12) & 0x0F);
  78. buffer[1] = 0x80 | ((wchar >> 6) & 0x3F);
  79. buffer[2] = 0x80 | (wchar & 0x3F);
  80. buffer[3] = 0;
  81. }
  82. }
  83. static int hex2decimal(char ch)
  84. {
  85. if (ch >= '0' && ch <= '9') {
  86. return (ch - '0');
  87. } else if (ch >= 'a' && ch <= 'f') {
  88. return 10 + (ch - 'a');
  89. } else if (ch >= 'A' && ch <= 'F') {
  90. return 10 + (ch - 'A');
  91. }
  92. return -1;
  93. }
  94. /**
  95. * parse_string(): Parse a JSON string
  96. *
  97. * From RFC 8259 "The JavaScript Object Notation (JSON) Data
  98. * Interchange Format":
  99. *
  100. * char = unescaped /
  101. * escape (
  102. * %x22 / ; " quotation mark U+0022
  103. * %x5C / ; \ reverse solidus U+005C
  104. * %x2F / ; / solidus U+002F
  105. * %x62 / ; b backspace U+0008
  106. * %x66 / ; f form feed U+000C
  107. * %x6E / ; n line feed U+000A
  108. * %x72 / ; r carriage return U+000D
  109. * %x74 / ; t tab U+0009
  110. * %x75 4HEXDIG ) ; uXXXX U+XXXX
  111. * escape = %x5C ; \
  112. * quotation-mark = %x22 ; "
  113. * unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
  114. *
  115. * Extensions over RFC 8259:
  116. * - Extra escape sequence in strings:
  117. * 0x27 (apostrophe) is recognized after escape, too
  118. * - Single-quoted strings:
  119. * Like double-quoted strings, except they're delimited by %x27
  120. * (apostrophe) instead of %x22 (quotation mark), and can't contain
  121. * unescaped apostrophe, but can contain unescaped quotation mark.
  122. *
  123. * Note:
  124. * - Encoding is modified UTF-8.
  125. * - Invalid Unicode characters are rejected.
  126. * - Control characters \x00..\x1F are rejected by the lexer.
  127. */
  128. static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
  129. {
  130. const char *ptr = token->str;
  131. QString *str;
  132. char quote;
  133. int cp;
  134. char *end;
  135. ssize_t len;
  136. char utf8_buf[5];
  137. assert(*ptr == '"' || *ptr == '\'');
  138. quote = *ptr++;
  139. str = qstring_new();
  140. while (*ptr != quote) {
  141. assert(*ptr);
  142. if (*ptr == '\\') {
  143. ptr++;
  144. switch (*ptr++) {
  145. case '"':
  146. qstring_append(str, "\"");
  147. break;
  148. case '\'':
  149. qstring_append(str, "'");
  150. break;
  151. case '\\':
  152. qstring_append(str, "\\");
  153. break;
  154. case '/':
  155. qstring_append(str, "/");
  156. break;
  157. case 'b':
  158. qstring_append(str, "\b");
  159. break;
  160. case 'f':
  161. qstring_append(str, "\f");
  162. break;
  163. case 'n':
  164. qstring_append(str, "\n");
  165. break;
  166. case 'r':
  167. qstring_append(str, "\r");
  168. break;
  169. case 't':
  170. qstring_append(str, "\t");
  171. break;
  172. case 'u': {
  173. uint16_t unicode_char = 0;
  174. char utf8_char[4];
  175. int i = 0;
  176. for (i = 0; i < 4; i++) {
  177. if (qemu_isxdigit(*ptr)) {
  178. unicode_char |= hex2decimal(*ptr) << ((3 - i) * 4);
  179. } else {
  180. parse_error(ctxt, token,
  181. "invalid hex escape sequence in string");
  182. goto out;
  183. }
  184. ptr++;
  185. }
  186. wchar_to_utf8(unicode_char, utf8_char, sizeof(utf8_char));
  187. qstring_append(str, utf8_char);
  188. } break;
  189. default:
  190. parse_error(ctxt, token, "invalid escape sequence in string");
  191. goto out;
  192. }
  193. } else {
  194. cp = mod_utf8_codepoint(ptr, 6, &end);
  195. if (cp < 0) {
  196. parse_error(ctxt, token, "invalid UTF-8 sequence in string");
  197. goto out;
  198. }
  199. ptr = end;
  200. len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp);
  201. assert(len >= 0);
  202. qstring_append(str, utf8_buf);
  203. }
  204. }
  205. return str;
  206. out:
  207. qobject_unref(str);
  208. return NULL;
  209. }
  210. /* Note: the token object returned by parser_context_peek_token or
  211. * parser_context_pop_token is deleted as soon as parser_context_pop_token
  212. * is called again.
  213. */
  214. static JSONToken *parser_context_pop_token(JSONParserContext *ctxt)
  215. {
  216. g_free(ctxt->current);
  217. assert(!g_queue_is_empty(ctxt->buf));
  218. ctxt->current = g_queue_pop_head(ctxt->buf);
  219. return ctxt->current;
  220. }
  221. static JSONToken *parser_context_peek_token(JSONParserContext *ctxt)
  222. {
  223. assert(!g_queue_is_empty(ctxt->buf));
  224. return g_queue_peek_head(ctxt->buf);
  225. }
  226. static JSONParserContext *parser_context_new(GQueue *tokens)
  227. {
  228. JSONParserContext *ctxt;
  229. if (!tokens) {
  230. return NULL;
  231. }
  232. ctxt = g_malloc0(sizeof(JSONParserContext));
  233. ctxt->buf = tokens;
  234. return ctxt;
  235. }
  236. /* to support error propagation, ctxt->err must be freed separately */
  237. static void parser_context_free(JSONParserContext *ctxt)
  238. {
  239. if (ctxt) {
  240. while (!g_queue_is_empty(ctxt->buf)) {
  241. parser_context_pop_token(ctxt);
  242. }
  243. g_free(ctxt->current);
  244. g_queue_free(ctxt->buf);
  245. g_free(ctxt);
  246. }
  247. }
  248. /**
  249. * Parsing rules
  250. */
  251. static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
  252. {
  253. QObject *value;
  254. QString *key = NULL;
  255. JSONToken *peek, *token;
  256. peek = parser_context_peek_token(ctxt);
  257. if (peek == NULL) {
  258. parse_error(ctxt, NULL, "premature EOI");
  259. goto out;
  260. }
  261. key = qobject_to(QString, parse_value(ctxt, ap));
  262. if (!key) {
  263. parse_error(ctxt, peek, "key is not a string in object");
  264. goto out;
  265. }
  266. token = parser_context_pop_token(ctxt);
  267. if (token == NULL) {
  268. parse_error(ctxt, NULL, "premature EOI");
  269. goto out;
  270. }
  271. if (token->type != JSON_COLON) {
  272. parse_error(ctxt, token, "missing : in object pair");
  273. goto out;
  274. }
  275. value = parse_value(ctxt, ap);
  276. if (value == NULL) {
  277. parse_error(ctxt, token, "Missing value in dict");
  278. goto out;
  279. }
  280. qdict_put_obj(dict, qstring_get_str(key), value);
  281. qobject_unref(key);
  282. return 0;
  283. out:
  284. qobject_unref(key);
  285. return -1;
  286. }
  287. static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
  288. {
  289. QDict *dict = NULL;
  290. JSONToken *token, *peek;
  291. token = parser_context_pop_token(ctxt);
  292. assert(token && token->type == JSON_LCURLY);
  293. dict = qdict_new();
  294. peek = parser_context_peek_token(ctxt);
  295. if (peek == NULL) {
  296. parse_error(ctxt, NULL, "premature EOI");
  297. goto out;
  298. }
  299. if (peek->type != JSON_RCURLY) {
  300. if (parse_pair(ctxt, dict, ap) == -1) {
  301. goto out;
  302. }
  303. token = parser_context_pop_token(ctxt);
  304. if (token == NULL) {
  305. parse_error(ctxt, NULL, "premature EOI");
  306. goto out;
  307. }
  308. while (token->type != JSON_RCURLY) {
  309. if (token->type != JSON_COMMA) {
  310. parse_error(ctxt, token, "expected separator in dict");
  311. goto out;
  312. }
  313. if (parse_pair(ctxt, dict, ap) == -1) {
  314. goto out;
  315. }
  316. token = parser_context_pop_token(ctxt);
  317. if (token == NULL) {
  318. parse_error(ctxt, NULL, "premature EOI");
  319. goto out;
  320. }
  321. }
  322. } else {
  323. (void)parser_context_pop_token(ctxt);
  324. }
  325. return QOBJECT(dict);
  326. out:
  327. qobject_unref(dict);
  328. return NULL;
  329. }
  330. static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
  331. {
  332. QList *list = NULL;
  333. JSONToken *token, *peek;
  334. token = parser_context_pop_token(ctxt);
  335. assert(token && token->type == JSON_LSQUARE);
  336. list = qlist_new();
  337. peek = parser_context_peek_token(ctxt);
  338. if (peek == NULL) {
  339. parse_error(ctxt, NULL, "premature EOI");
  340. goto out;
  341. }
  342. if (peek->type != JSON_RSQUARE) {
  343. QObject *obj;
  344. obj = parse_value(ctxt, ap);
  345. if (obj == NULL) {
  346. parse_error(ctxt, token, "expecting value");
  347. goto out;
  348. }
  349. qlist_append_obj(list, obj);
  350. token = parser_context_pop_token(ctxt);
  351. if (token == NULL) {
  352. parse_error(ctxt, NULL, "premature EOI");
  353. goto out;
  354. }
  355. while (token->type != JSON_RSQUARE) {
  356. if (token->type != JSON_COMMA) {
  357. parse_error(ctxt, token, "expected separator in list");
  358. goto out;
  359. }
  360. obj = parse_value(ctxt, ap);
  361. if (obj == NULL) {
  362. parse_error(ctxt, token, "expecting value");
  363. goto out;
  364. }
  365. qlist_append_obj(list, obj);
  366. token = parser_context_pop_token(ctxt);
  367. if (token == NULL) {
  368. parse_error(ctxt, NULL, "premature EOI");
  369. goto out;
  370. }
  371. }
  372. } else {
  373. (void)parser_context_pop_token(ctxt);
  374. }
  375. return QOBJECT(list);
  376. out:
  377. qobject_unref(list);
  378. return NULL;
  379. }
  380. static QObject *parse_keyword(JSONParserContext *ctxt)
  381. {
  382. JSONToken *token;
  383. token = parser_context_pop_token(ctxt);
  384. assert(token && token->type == JSON_KEYWORD);
  385. if (!strcmp(token->str, "true")) {
  386. return QOBJECT(qbool_from_bool(true));
  387. } else if (!strcmp(token->str, "false")) {
  388. return QOBJECT(qbool_from_bool(false));
  389. } else if (!strcmp(token->str, "null")) {
  390. return QOBJECT(qnull());
  391. }
  392. parse_error(ctxt, token, "invalid keyword '%s'", token->str);
  393. return NULL;
  394. }
  395. static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
  396. {
  397. JSONToken *token;
  398. if (ap == NULL) {
  399. return NULL;
  400. }
  401. token = parser_context_pop_token(ctxt);
  402. assert(token && token->type == JSON_ESCAPE);
  403. if (!strcmp(token->str, "%p")) {
  404. return va_arg(*ap, QObject *);
  405. } else if (!strcmp(token->str, "%i")) {
  406. return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
  407. } else if (!strcmp(token->str, "%d")) {
  408. return QOBJECT(qnum_from_int(va_arg(*ap, int)));
  409. } else if (!strcmp(token->str, "%ld")) {
  410. return QOBJECT(qnum_from_int(va_arg(*ap, long)));
  411. } else if (!strcmp(token->str, "%lld") ||
  412. !strcmp(token->str, "%I64d")) {
  413. return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
  414. } else if (!strcmp(token->str, "%u")) {
  415. return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
  416. } else if (!strcmp(token->str, "%lu")) {
  417. return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
  418. } else if (!strcmp(token->str, "%llu") ||
  419. !strcmp(token->str, "%I64u")) {
  420. return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
  421. } else if (!strcmp(token->str, "%s")) {
  422. return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
  423. } else if (!strcmp(token->str, "%f")) {
  424. return QOBJECT(qnum_from_double(va_arg(*ap, double)));
  425. }
  426. return NULL;
  427. }
  428. static QObject *parse_literal(JSONParserContext *ctxt)
  429. {
  430. JSONToken *token;
  431. token = parser_context_pop_token(ctxt);
  432. assert(token);
  433. switch (token->type) {
  434. case JSON_STRING:
  435. return QOBJECT(parse_string(ctxt, token));
  436. case JSON_INTEGER: {
  437. /*
  438. * Represent JSON_INTEGER as QNUM_I64 if possible, else as
  439. * QNUM_U64, else as QNUM_DOUBLE. Note that qemu_strtoi64()
  440. * and qemu_strtou64() fail with ERANGE when it's not
  441. * possible.
  442. *
  443. * qnum_get_int() will then work for any signed 64-bit
  444. * JSON_INTEGER, qnum_get_uint() for any unsigned 64-bit
  445. * integer, and qnum_get_double() both for any JSON_INTEGER
  446. * and any JSON_FLOAT (with precision loss for integers beyond
  447. * 53 bits)
  448. */
  449. int ret;
  450. int64_t value;
  451. uint64_t uvalue;
  452. ret = qemu_strtoi64(token->str, NULL, 10, &value);
  453. if (!ret) {
  454. return QOBJECT(qnum_from_int(value));
  455. }
  456. assert(ret == -ERANGE);
  457. if (token->str[0] != '-') {
  458. ret = qemu_strtou64(token->str, NULL, 10, &uvalue);
  459. if (!ret) {
  460. return QOBJECT(qnum_from_uint(uvalue));
  461. }
  462. assert(ret == -ERANGE);
  463. }
  464. /* fall through to JSON_FLOAT */
  465. }
  466. case JSON_FLOAT:
  467. /* FIXME dependent on locale; a pervasive issue in QEMU */
  468. /* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN,
  469. * but those might be useful extensions beyond JSON */
  470. return QOBJECT(qnum_from_double(strtod(token->str, NULL)));
  471. default:
  472. abort();
  473. }
  474. }
  475. static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
  476. {
  477. JSONToken *token;
  478. token = parser_context_peek_token(ctxt);
  479. if (token == NULL) {
  480. parse_error(ctxt, NULL, "premature EOI");
  481. return NULL;
  482. }
  483. switch (token->type) {
  484. case JSON_LCURLY:
  485. return parse_object(ctxt, ap);
  486. case JSON_LSQUARE:
  487. return parse_array(ctxt, ap);
  488. case JSON_ESCAPE:
  489. return parse_escape(ctxt, ap);
  490. case JSON_INTEGER:
  491. case JSON_FLOAT:
  492. case JSON_STRING:
  493. return parse_literal(ctxt);
  494. case JSON_KEYWORD:
  495. return parse_keyword(ctxt);
  496. default:
  497. parse_error(ctxt, token, "expecting value");
  498. return NULL;
  499. }
  500. }
  501. QObject *json_parser_parse(GQueue *tokens, va_list *ap)
  502. {
  503. return json_parser_parse_err(tokens, ap, NULL);
  504. }
  505. QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
  506. {
  507. JSONParserContext *ctxt = parser_context_new(tokens);
  508. QObject *result;
  509. if (!ctxt) {
  510. return NULL;
  511. }
  512. result = parse_value(ctxt, ap);
  513. error_propagate(errp, ctxt->err);
  514. parser_context_free(ctxt);
  515. return result;
  516. }