@@ -27,7 +27,6 @@ typedef enum json_token_type {
JSON_FLOAT,
JSON_KEYWORD,
JSON_STRING,
- JSON_ESCAPE,
JSON_SKIP,
JSON_ERROR,
} JSONTokenType;
@@ -58,12 +58,6 @@ enum json_lexer_state {
IN_NONZERO_NUMBER,
IN_NEG_NONZERO_NUMBER,
IN_KEYWORD,
- IN_ESCAPE,
- IN_ESCAPE_L,
- IN_ESCAPE_LL,
- IN_ESCAPE_I,
- IN_ESCAPE_I6,
- IN_ESCAPE_I64,
IN_WHITESPACE,
IN_START,
};
@@ -224,38 +218,6 @@ static const uint8_t json_lexer[][256] = {
['\n'] = IN_WHITESPACE,
},
- /* escape */
- [IN_ESCAPE_LL] = {
- ['d'] = JSON_ESCAPE,
- },
-
- [IN_ESCAPE_L] = {
- ['d'] = JSON_ESCAPE,
- ['l'] = IN_ESCAPE_LL,
- },
-
- [IN_ESCAPE_I64] = {
- ['d'] = JSON_ESCAPE,
- },
-
- [IN_ESCAPE_I6] = {
- ['4'] = IN_ESCAPE_I64,
- },
-
- [IN_ESCAPE_I] = {
- ['6'] = IN_ESCAPE_I6,
- },
-
- [IN_ESCAPE] = {
- ['d'] = JSON_ESCAPE,
- ['i'] = JSON_ESCAPE,
- ['p'] = JSON_ESCAPE,
- ['s'] = JSON_ESCAPE,
- ['f'] = JSON_ESCAPE,
- ['l'] = IN_ESCAPE_L,
- ['I'] = IN_ESCAPE_I,
- },
-
/* top level rule */
[IN_START] = {
['"'] = IN_DQ_STRING,
@@ -270,7 +232,6 @@ static const uint8_t json_lexer[][256] = {
[','] = JSON_COMMA,
[':'] = JSON_COLON,
['a' ... 'z'] = IN_KEYWORD,
- ['%'] = IN_ESCAPE,
[' '] = IN_WHITESPACE,
['\t'] = IN_WHITESPACE,
['\r'] = IN_WHITESPACE,
@@ -311,7 +272,6 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
case JSON_RSQUARE:
case JSON_COLON:
case JSON_COMMA:
- case JSON_ESCAPE:
case JSON_INTEGER:
case JSON_FLOAT:
case JSON_KEYWORD:
@@ -450,36 +450,6 @@ static QObject *parse_keyword(JSONParserContext *ctxt)
return NULL;
}
-static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
-{
- JSONToken *token;
-
- if (ap == NULL) {
- return NULL;
- }
-
- token = parser_context_pop_token(ctxt);
- assert(token && token->type == JSON_ESCAPE);
-
- if (!strcmp(token->str, "%p")) {
- return va_arg(*ap, QObject *);
- } else if (!strcmp(token->str, "%i")) {
- return QOBJECT(qbool_from_bool(va_arg(*ap, int)));
- } else if (!strcmp(token->str, "%d")) {
- return QOBJECT(qint_from_int(va_arg(*ap, int)));
- } else if (!strcmp(token->str, "%ld")) {
- return QOBJECT(qint_from_int(va_arg(*ap, long)));
- } else if (!strcmp(token->str, "%lld") ||
- !strcmp(token->str, "%I64d")) {
- return QOBJECT(qint_from_int(va_arg(*ap, long long)));
- } else if (!strcmp(token->str, "%s")) {
- return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
- } else if (!strcmp(token->str, "%f")) {
- return QOBJECT(qfloat_from_double(va_arg(*ap, double)));
- }
- return NULL;
-}
-
static QObject *parse_literal(JSONParserContext *ctxt)
{
JSONToken *token;
@@ -537,8 +507,6 @@ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
return parse_object(ctxt, ap);
case JSON_LSQUARE:
return parse_array(ctxt, ap);
- case JSON_ESCAPE:
- return parse_escape(ctxt, ap);
case JSON_INTEGER:
case JSON_FLOAT:
case JSON_STRING:
Now that there are no callers of dynamic JSON parsing, the lexer does not need to special-case escape sequences. Since the lexer is directly invoked on user-provided input, this changes behavior when a QMP client passes (bad) JSON, from: {'execute':'qmp_capabilities','id':%s} {"error": {"class": "GenericError", "desc": "Invalid JSON syntax"}} to the noisier: {'execute':'qmp_capabilities','id':%s} {"error": {"class": "GenericError", "desc": "Invalid JSON syntax"}} {"error": {"class": "GenericError", "desc": "JSON parse error, invalid keyword 's'"}} {"error": {"class": "GenericError", "desc": "JSON parse error, expecting value"}} But we've always known our parser is rather noisy when it comes to dealing with invalid JSON, and valid clients won't see the difference. Signed-off-by: Eric Blake <eblake@redhat.com> --- include/qapi/qmp/json-lexer.h | 1 - qobject/json-lexer.c | 40 ---------------------------------------- qobject/json-parser.c | 32 -------------------------------- 3 files changed, 73 deletions(-)