Diff for /qemu/json-lexer.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2018/04/24 18:23:35 version 1.1.1.4, 2018/04/24 18:55:53
Line 18 Line 18
 #include "qemu-common.h"  #include "qemu-common.h"
 #include "json-lexer.h"  #include "json-lexer.h"
   
   #define MAX_TOKEN_SIZE (64ULL << 20)
   
 /*  /*
  * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\"   * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\"
  * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*'   * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*'
Line 28 Line 30
  */   */
   
 enum json_lexer_state {  enum json_lexer_state {
     ERROR = 0,      IN_ERROR = 0,
     IN_DQ_UCODE3,      IN_DQ_UCODE3,
     IN_DQ_UCODE2,      IN_DQ_UCODE2,
     IN_DQ_UCODE1,      IN_DQ_UCODE1,
Line 103  static const uint8_t json_lexer[][256] = Line 105  static const uint8_t json_lexer[][256] =
         ['u'] = IN_DQ_UCODE0,          ['u'] = IN_DQ_UCODE0,
     },      },
     [IN_DQ_STRING] = {      [IN_DQ_STRING] = {
         [1 ... 0xFF] = IN_DQ_STRING,          [1 ... 0xBF] = IN_DQ_STRING,
           [0xC2 ... 0xF4] = IN_DQ_STRING,
         ['\\'] = IN_DQ_STRING_ESCAPE,          ['\\'] = IN_DQ_STRING_ESCAPE,
         ['"'] = JSON_STRING,          ['"'] = JSON_STRING,
     },      },
Line 142  static const uint8_t json_lexer[][256] = Line 145  static const uint8_t json_lexer[][256] =
         ['u'] = IN_SQ_UCODE0,          ['u'] = IN_SQ_UCODE0,
     },      },
     [IN_SQ_STRING] = {      [IN_SQ_STRING] = {
         [1 ... 0xFF] = IN_SQ_STRING,          [1 ... 0xBF] = IN_SQ_STRING,
           [0xC2 ... 0xF4] = IN_SQ_STRING,
         ['\\'] = IN_SQ_STRING_ESCAPE,          ['\\'] = IN_SQ_STRING_ESCAPE,
         ['\''] = JSON_STRING,          ['\''] = JSON_STRING,
     },      },
Line 150  static const uint8_t json_lexer[][256] = Line 154  static const uint8_t json_lexer[][256] =
     /* Zero */      /* Zero */
     [IN_ZERO] = {      [IN_ZERO] = {
         TERMINAL(JSON_INTEGER),          TERMINAL(JSON_INTEGER),
         ['0' ... '9'] = ERROR,          ['0' ... '9'] = IN_ERROR,
         ['.'] = IN_MANTISSA,          ['.'] = IN_MANTISSA,
     },      },
   
Line 272  void json_lexer_init(JSONLexer *lexer, J Line 276  void json_lexer_init(JSONLexer *lexer, J
     lexer->x = lexer->y = 0;      lexer->x = lexer->y = 0;
 }  }
   
 static int json_lexer_feed_char(JSONLexer *lexer, char ch)  static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
 {  {
     int char_consumed, new_state;      int char_consumed, new_state;
   
Line 302  static int json_lexer_feed_char(JSONLexe Line 306  static int json_lexer_feed_char(JSONLexe
             lexer->token = qstring_new();              lexer->token = qstring_new();
             new_state = IN_START;              new_state = IN_START;
             break;              break;
         case ERROR:          case IN_ERROR:
             return -EINVAL;              /* XXX: To avoid having previous bad input leaving the parser in an
                * unresponsive state where we consume unpredictable amounts of
                * subsequent "good" input, percolate this error state up to the
                * tokenizer/parser by forcing a NULL object to be emitted, then
                * reset state.
                *
                * Also note that this handling is required for reliable channel
                * negotiation between QMP and the guest agent, since chr(0xFF)
                * is placed at the beginning of certain events to ensure proper
                * delivery when the channel is in an unknown state. chr(0xFF) is
                * never a valid ASCII/UTF-8 sequence, so this should reliably
                * induce an error/flush state.
                */
               lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y);
               QDECREF(lexer->token);
               lexer->token = qstring_new();
               new_state = IN_START;
               lexer->state = new_state;
               return 0;
         default:          default:
             break;              break;
         }          }
         lexer->state = new_state;          lexer->state = new_state;
     } while (!char_consumed);      } while (!char_consumed && !flush);
   
       /* Do not let a single token grow to an arbitrarily large size,
        * this is a security consideration.
        */
       if (lexer->token->length > MAX_TOKEN_SIZE) {
           lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
           QDECREF(lexer->token);
           lexer->token = qstring_new();
           lexer->state = IN_START;
       }
   
     return 0;      return 0;
 }  }
   
Line 319  int json_lexer_feed(JSONLexer *lexer, co Line 352  int json_lexer_feed(JSONLexer *lexer, co
     for (i = 0; i < size; i++) {      for (i = 0; i < size; i++) {
         int err;          int err;
   
         err = json_lexer_feed_char(lexer, buffer[i]);          err = json_lexer_feed_char(lexer, buffer[i], false);
         if (err < 0) {          if (err < 0) {
             return err;              return err;
         }          }
Line 330  int json_lexer_feed(JSONLexer *lexer, co Line 363  int json_lexer_feed(JSONLexer *lexer, co
   
 int json_lexer_flush(JSONLexer *lexer)  int json_lexer_flush(JSONLexer *lexer)
 {  {
     return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0);      return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true);
 }  }
   
 void json_lexer_destroy(JSONLexer *lexer)  void json_lexer_destroy(JSONLexer *lexer)

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


unix.superglobalmegacorp.com