Beispiel #1
0
/* We are converting a UTF-32 character into UTF-8 here,
 * as described by RFC3629.
 */
static void json_reader_string_add_utf32(void* userdata, gpr_uint32 c) {
  if (c <= 0x7f) {
    json_reader_string_add_char(userdata, c);
  } else if (c <= 0x7ff) {
    gpr_uint32 b1 = 0xc0 | ((c >> 6) & 0x1f);
    gpr_uint32 b2 = 0x80 | (c & 0x3f);
    json_reader_string_add_char(userdata, b1);
    json_reader_string_add_char(userdata, b2);
  } else if (c <= 0xffff) {
Beispiel #2
0
static void json_reader_string_add_utf32(void *userdata, uint32_t c) {
  if (c <= 0x7f) {
    json_reader_string_add_char(userdata, c);
  } else if (c <= 0x7ffu) {
    uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu);
    uint32_t b2 = 0x80u | (c & 0x3fu);
    json_reader_string_add_char(userdata, b1);
    json_reader_string_add_char(userdata, b2);
  } else if (c <= 0xffffu) {
Beispiel #3
0
grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
  uint32_t c, success;

  /* This state-machine is a strict implementation of ECMA-404 */
  for (;;) {
    c = grpc_json_reader_read_char(reader);
    switch (c) {
      /* Let's process the error cases first. */
      case GRPC_JSON_READ_CHAR_ERROR:
        return GRPC_JSON_READ_ERROR;

      case GRPC_JSON_READ_CHAR_EAGAIN:
        return GRPC_JSON_EAGAIN;

      case GRPC_JSON_READ_CHAR_EOF:
        if (grpc_json_reader_is_complete(reader)) {
          return GRPC_JSON_DONE;
        } else {
          return GRPC_JSON_PARSE_ERROR;
        }
        break;

      /* Processing whitespaces. */
      case ' ':
      case '\t':
      case '\n':
      case '\r':
        switch (reader->state) {
          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
          case GRPC_JSON_STATE_OBJECT_KEY_END:
          case GRPC_JSON_STATE_VALUE_BEGIN:
          case GRPC_JSON_STATE_VALUE_END:
          case GRPC_JSON_STATE_END:
            break;

          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
          case GRPC_JSON_STATE_VALUE_STRING:
            if (c != ' ') return GRPC_JSON_PARSE_ERROR;
            if (reader->unicode_high_surrogate != 0)
              return GRPC_JSON_PARSE_ERROR;
            json_reader_string_add_char(reader, c);
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER:
          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
            success = (uint32_t)json_reader_set_number(reader);
            if (!success) return GRPC_JSON_PARSE_ERROR;
            json_reader_string_clear(reader);
            reader->state = GRPC_JSON_STATE_VALUE_END;
            break;

          default:
            return GRPC_JSON_PARSE_ERROR;
        }
        break;

      /* Value, object or array terminations. */
      case ',':
      case '}':
      case ']':
        switch (reader->state) {
          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
          case GRPC_JSON_STATE_VALUE_STRING:
            if (reader->unicode_high_surrogate != 0)
              return GRPC_JSON_PARSE_ERROR;
            json_reader_string_add_char(reader, c);
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER:
          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
            success = (uint32_t)json_reader_set_number(reader);
            if (!success) return GRPC_JSON_PARSE_ERROR;
            json_reader_string_clear(reader);
            reader->state = GRPC_JSON_STATE_VALUE_END;
          /* The missing break here is intentional. */

          case GRPC_JSON_STATE_VALUE_END:
          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
          case GRPC_JSON_STATE_VALUE_BEGIN:
            if (c == ',') {
              if (reader->state != GRPC_JSON_STATE_VALUE_END) {
                return GRPC_JSON_PARSE_ERROR;
              }
              if (reader->in_object) {
                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
              } else {
                reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
              }
            } else {
              if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR;
              if ((c == '}') && !reader->in_object) {
                return GRPC_JSON_PARSE_ERROR;
              }
              if ((c == '}') &&
                  (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) &&
                  !reader->container_just_begun) {
                return GRPC_JSON_PARSE_ERROR;
              }
              if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR;
              if ((c == ']') &&
                  (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) &&
                  !reader->container_just_begun) {
                return GRPC_JSON_PARSE_ERROR;
              }
              reader->state = GRPC_JSON_STATE_VALUE_END;
              switch (grpc_json_reader_container_ends(reader)) {
                case GRPC_JSON_OBJECT:
                  reader->in_object = 1;
                  reader->in_array = 0;
                  break;
                case GRPC_JSON_ARRAY:
                  reader->in_object = 0;
                  reader->in_array = 1;
                  break;
                case GRPC_JSON_TOP_LEVEL:
                  GPR_ASSERT(reader->depth == 0);
                  reader->in_object = 0;
                  reader->in_array = 0;
                  reader->state = GRPC_JSON_STATE_END;
                  break;
                default:
                  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
              }
            }
            break;

          default:
            return GRPC_JSON_PARSE_ERROR;
        }
        break;

      /* In-string escaping. */
      case '\\':
        switch (reader->state) {
          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
            reader->escaped_string_was_key = 1;
            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
            break;

          case GRPC_JSON_STATE_VALUE_STRING:
            reader->escaped_string_was_key = 0;
            reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
            break;

          /* This is the \\ case. */
          case GRPC_JSON_STATE_STRING_ESCAPE:
            if (reader->unicode_high_surrogate != 0)
              return GRPC_JSON_PARSE_ERROR;
            json_reader_string_add_char(reader, '\\');
            if (reader->escaped_string_was_key) {
              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
            } else {
              reader->state = GRPC_JSON_STATE_VALUE_STRING;
            }
            break;

          default:
            return GRPC_JSON_PARSE_ERROR;
        }
        break;

      default:
        reader->container_just_begun = 0;
        switch (reader->state) {
          case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
            if (c != '"') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
            break;

          case GRPC_JSON_STATE_OBJECT_KEY_STRING:
            if (reader->unicode_high_surrogate != 0)
              return GRPC_JSON_PARSE_ERROR;
            if (c == '"') {
              reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
              json_reader_set_key(reader);
              json_reader_string_clear(reader);
            } else {
              if (c < 32) return GRPC_JSON_PARSE_ERROR;
              json_reader_string_add_char(reader, c);
            }
            break;

          case GRPC_JSON_STATE_VALUE_STRING:
            if (reader->unicode_high_surrogate != 0)
              return GRPC_JSON_PARSE_ERROR;
            if (c == '"') {
              reader->state = GRPC_JSON_STATE_VALUE_END;
              json_reader_set_string(reader);
              json_reader_string_clear(reader);
            } else {
              if (c < 32) return GRPC_JSON_PARSE_ERROR;
              json_reader_string_add_char(reader, c);
            }
            break;

          case GRPC_JSON_STATE_OBJECT_KEY_END:
            if (c != ':') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
            break;

          case GRPC_JSON_STATE_VALUE_BEGIN:
            switch (c) {
              case 't':
                reader->state = GRPC_JSON_STATE_VALUE_TRUE_R;
                break;

              case 'f':
                reader->state = GRPC_JSON_STATE_VALUE_FALSE_A;
                break;

              case 'n':
                reader->state = GRPC_JSON_STATE_VALUE_NULL_U;
                break;

              case '"':
                reader->state = GRPC_JSON_STATE_VALUE_STRING;
                break;

              case '0':
                json_reader_string_add_char(reader, c);
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO;
                break;

              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
              case '-':
                json_reader_string_add_char(reader, c);
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER;
                break;

              case '{':
                reader->container_just_begun = 1;
                json_reader_container_begins(reader, GRPC_JSON_OBJECT);
                reader->depth++;
                reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
                reader->in_object = 1;
                reader->in_array = 0;
                break;

              case '[':
                reader->container_just_begun = 1;
                json_reader_container_begins(reader, GRPC_JSON_ARRAY);
                reader->depth++;
                reader->in_object = 0;
                reader->in_array = 1;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_STRING_ESCAPE:
            if (reader->escaped_string_was_key) {
              reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
            } else {
              reader->state = GRPC_JSON_STATE_VALUE_STRING;
            }
            if (reader->unicode_high_surrogate && c != 'u')
              return GRPC_JSON_PARSE_ERROR;
            switch (c) {
              case '"':
              case '/':
                json_reader_string_add_char(reader, c);
                break;
              case 'b':
                json_reader_string_add_char(reader, '\b');
                break;
              case 'f':
                json_reader_string_add_char(reader, '\f');
                break;
              case 'n':
                json_reader_string_add_char(reader, '\n');
                break;
              case 'r':
                json_reader_string_add_char(reader, '\r');
                break;
              case 't':
                json_reader_string_add_char(reader, '\t');
                break;
              case 'u':
                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1;
                reader->unicode_char = 0;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_STRING_ESCAPE_U1:
          case GRPC_JSON_STATE_STRING_ESCAPE_U2:
          case GRPC_JSON_STATE_STRING_ESCAPE_U3:
          case GRPC_JSON_STATE_STRING_ESCAPE_U4:
            if ((c >= '0') && (c <= '9')) {
              c -= '0';
            } else if ((c >= 'A') && (c <= 'F')) {
              c -= 'A' - 10;
            } else if ((c >= 'a') && (c <= 'f')) {
              c -= 'a' - 10;
            } else {
              return GRPC_JSON_PARSE_ERROR;
            }
            reader->unicode_char = (uint16_t)(reader->unicode_char << 4);
            reader->unicode_char = (uint16_t)(reader->unicode_char | c);

            switch (reader->state) {
              case GRPC_JSON_STATE_STRING_ESCAPE_U1:
                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2;
                break;
              case GRPC_JSON_STATE_STRING_ESCAPE_U2:
                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3;
                break;
              case GRPC_JSON_STATE_STRING_ESCAPE_U3:
                reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4;
                break;
              case GRPC_JSON_STATE_STRING_ESCAPE_U4:
                /* See grpc_json_writer_escape_string to have a description
                 * of what's going on here.
                 */
                if ((reader->unicode_char & 0xfc00) == 0xd800) {
                  /* high surrogate utf-16 */
                  if (reader->unicode_high_surrogate != 0)
                    return GRPC_JSON_PARSE_ERROR;
                  reader->unicode_high_surrogate = reader->unicode_char;
                } else if ((reader->unicode_char & 0xfc00) == 0xdc00) {
                  /* low surrogate utf-16 */
                  uint32_t utf32;
                  if (reader->unicode_high_surrogate == 0)
                    return GRPC_JSON_PARSE_ERROR;
                  utf32 = 0x10000;
                  utf32 += (uint32_t)(
                      (reader->unicode_high_surrogate - 0xd800) * 0x400);
                  utf32 += (uint32_t)(reader->unicode_char - 0xdc00);
                  json_reader_string_add_utf32(reader, utf32);
                  reader->unicode_high_surrogate = 0;
                } else {
                  /* anything else */
                  if (reader->unicode_high_surrogate != 0)
                    return GRPC_JSON_PARSE_ERROR;
                  json_reader_string_add_utf32(reader, reader->unicode_char);
                }
                if (reader->escaped_string_was_key) {
                  reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
                } else {
                  reader->state = GRPC_JSON_STATE_VALUE_STRING;
                }
                break;
              default:
                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
            }
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER:
            json_reader_string_add_char(reader, c);
            switch (c) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
                break;
              case 'e':
              case 'E':
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
                break;
              case '.':
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
            json_reader_string_add_char(reader, c);
            switch (c) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
                break;
              case 'e':
              case 'E':
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
            if (c != '.') return GRPC_JSON_PARSE_ERROR;
            json_reader_string_add_char(reader, c);
            reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER_DOT:
            json_reader_string_add_char(reader, c);
            switch (c) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER_E:
            json_reader_string_add_char(reader, c);
            switch (c) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
              case '+':
              case '-':
                reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM;
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
            json_reader_string_add_char(reader, c);
            switch (c) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
                break;
              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_VALUE_TRUE_R:
            if (c != 'r') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_TRUE_U;
            break;

          case GRPC_JSON_STATE_VALUE_TRUE_U:
            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_TRUE_E;
            break;

          case GRPC_JSON_STATE_VALUE_TRUE_E:
            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
            json_reader_set_true(reader);
            reader->state = GRPC_JSON_STATE_VALUE_END;
            break;

          case GRPC_JSON_STATE_VALUE_FALSE_A:
            if (c != 'a') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_FALSE_L;
            break;

          case GRPC_JSON_STATE_VALUE_FALSE_L:
            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_FALSE_S;
            break;

          case GRPC_JSON_STATE_VALUE_FALSE_S:
            if (c != 's') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_FALSE_E;
            break;

          case GRPC_JSON_STATE_VALUE_FALSE_E:
            if (c != 'e') return GRPC_JSON_PARSE_ERROR;
            json_reader_set_false(reader);
            reader->state = GRPC_JSON_STATE_VALUE_END;
            break;

          case GRPC_JSON_STATE_VALUE_NULL_U:
            if (c != 'u') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_NULL_L1;
            break;

          case GRPC_JSON_STATE_VALUE_NULL_L1:
            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
            reader->state = GRPC_JSON_STATE_VALUE_NULL_L2;
            break;

          case GRPC_JSON_STATE_VALUE_NULL_L2:
            if (c != 'l') return GRPC_JSON_PARSE_ERROR;
            json_reader_set_null(reader);
            reader->state = GRPC_JSON_STATE_VALUE_END;
            break;

          /* All of the VALUE_END cases are handled in the specialized case
           * above. */
          case GRPC_JSON_STATE_VALUE_END:
            switch (c) {
              case ',':
              case '}':
              case ']':
                GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
                break;

              default:
                return GRPC_JSON_PARSE_ERROR;
            }
            break;

          case GRPC_JSON_STATE_END:
            return GRPC_JSON_PARSE_ERROR;
        }
    }
  }

  GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
}