Ejemplo n.º 1
0
json_t *bunser(const char *buf, const char *end, int *needed,
               json_error_t *jerr)
{
    json_int_t ival;

    switch (buf[0]) {
    case BSER_INT8:
    case BSER_INT16:
    case BSER_INT32:
    case BSER_INT64:
        if (!bunser_int(buf, end - buf, needed, &ival)) {
            snprintf(jerr->text, sizeof(jerr->text),
                     "invalid integer encoding");
            return NULL;
        }
        return json_integer(ival);

    case BSER_STRING:
    {
        const char *start;
        json_int_t len;

        if (!bunser_string(buf, end - buf, needed, &start, &len)) {
            snprintf(jerr->text, sizeof(jerr->text),
                     "invalid string encoding");
            return NULL;
        }

        return json_string_binary(start, len);
    }

    case BSER_REAL:
        *needed = sizeof(double) + 1;
        return json_real(*(double*)(buf+1));
    case BSER_TRUE:
        *needed = 1;
        return json_true();
    case BSER_FALSE:
        *needed = 1;
        return json_false();
    case BSER_NULL:
        *needed = 1;
        return json_null();
    case BSER_ARRAY:
        return bunser_array(buf, end, needed, jerr);
    case BSER_TEMPLATE:
        return bunser_template(buf, end, needed, jerr);
    case BSER_OBJECT:
        return bunser_object(buf, end, needed, jerr);
    default:
        snprintf(jerr->text, sizeof(jerr->text),
                 "invalid bser encoding type %02x", (int)buf[0]);
        return NULL;
    }

    return NULL;
}
Ejemplo n.º 2
0
static json_t *bunser_array(const char *buf, const char *end,
    json_int_t *used, json_error_t *jerr)
{
  json_int_t needed;
  json_int_t total = 0;
  json_int_t i, nelems;
  json_t *arrval;

  buf++;
  total++;

  if (!bunser_int(buf, end - buf, &needed, &nelems)) {
    if (needed == -1) {
      snprintf(jerr->text, sizeof(jerr->text),
          "invalid integer encoding 0x%02x for array length. buf=%p\n",
          (int)buf[0], buf);
      return NULL;
    }
    *used = needed + total;
    snprintf(jerr->text, sizeof(jerr->text),
        "invalid array length encoding 0x%02x (needed %d but have %d)",
        (int)buf[0], (int)needed, (int)(end - buf));
    return NULL;
  }

  total += needed;
  buf += needed;

  arrval = json_array();
  for (i = 0; i < nelems; i++) {
    json_t *item;

    needed = 0;
    item = bunser(buf, end, &needed, jerr);

    total += needed;
    buf += needed;

    if (!item) {
      json_decref(arrval);
      *used = total;
      return NULL;
    }

    if (json_array_append_new(arrval, item)) {
      json_decref(arrval);
      *used = total;
      snprintf(jerr->text, sizeof(jerr->text),
        "failed to append array item");
      return NULL;
    }
  }

  *used = total;
  return arrval;
}
Ejemplo n.º 3
0
bool w_bser_decode_pdu_info(w_jbuffer_t *jr, w_stm_t stm, uint32_t bser_version,
    json_int_t *len, json_int_t *bser_capabilities, json_error_t *jerr)
{
  json_int_t needed;
  if (bser_version == 2) {
    while (!bunser_int(jr->buf + jr->rpos, jr->wpos - jr->rpos,
          &needed, bser_capabilities)) {
      if (needed == -1) {
        snprintf(jerr->text, sizeof(jerr->text),
            "failed to read BSER capabilities");
        return false;
      }
      if (!fill_buffer(jr, stm)) {
        snprintf(jerr->text, sizeof(jerr->text),
            "unable to fill buffer");
        return false;
      }
    }
    jr->rpos += (uint32_t)needed;
  }
  while (!bunser_int(jr->buf + jr->rpos, jr->wpos - jr->rpos,
        &needed, len)) {
    if (needed == -1) {
      snprintf(jerr->text, sizeof(jerr->text),
          "failed to read PDU size");
      return false;
    }
    if (!fill_buffer(jr, stm)) {
      snprintf(jerr->text, sizeof(jerr->text),
          "unable to fill buffer");
      return false;
    }
  }
  jr->rpos += (uint32_t)needed;

  return true;
}
Ejemplo n.º 4
0
bool bunser_bytestring(const char *buf, json_int_t avail, json_int_t *needed,
    const char **start, json_int_t *len)
{
  json_int_t ineed;

  if (!bunser_int(buf + 1, avail - 1, &ineed, len)) {
    *needed = ineed;
    return false;
  }

  buf += ineed + 1;
  avail -= ineed + 1;
  *needed = ineed + 1 + *len;

  if (*len > avail) {
    return false;
  }

  *start = buf;
  return true;
}
Ejemplo n.º 5
0
bool w_bser_decode_pdu_len(w_jbuffer_t *jr, w_stm_t stm,
    json_int_t *len, json_error_t *jerr)
{
  json_int_t needed;

  while (!bunser_int(jr->buf + jr->rpos, jr->wpos - jr->rpos,
        &needed, len)) {
    if (needed == -1) {
      snprintf(jerr->text, sizeof(jerr->text),
          "failed to read PDU size");
      return false;
    }
    if (!fill_buffer(jr, stm)) {
      snprintf(jerr->text, sizeof(jerr->text),
          "unable to fill buffer");
      return false;
    }
  }
  jr->rpos += (uint32_t)needed;

  return true;
}
Ejemplo n.º 6
0
json_t *bunser(const char *buf, const char *end, json_int_t *needed,
    json_error_t *jerr)
{
  json_int_t ival;

  switch (buf[0]) {
    case BSER_INT8:
    case BSER_INT16:
    case BSER_INT32:
    case BSER_INT64:
      if (!bunser_int(buf, end - buf, needed, &ival)) {
        snprintf(jerr->text, sizeof(jerr->text),
            "invalid integer encoding");
        return NULL;
      }
      return json_integer(ival);

    case BSER_BYTESTRING:
    {
      const char *start;
      json_int_t len;

      if (!bunser_bytestring(buf, end - buf, needed, &start, &len)) {
        snprintf(jerr->text, sizeof(jerr->text),
            "invalid bytestring encoding");
        return NULL;
      }

      return json_stringn_nocheck(start, len);
    }

    case BSER_REAL:
    {
      double dval;
      *needed = sizeof(double) + 1;
      memcpy(&dval, buf + 1, sizeof(dval));
      return json_real(dval);
    }

    case BSER_TRUE:
      *needed = 1;
      return json_true();
    case BSER_FALSE:
      *needed = 1;
      return json_false();
    case BSER_NULL:
      *needed = 1;
      return json_null();
    case BSER_ARRAY:
      return bunser_array(buf, end, needed, jerr);
    case BSER_TEMPLATE:
      return bunser_template(buf, end, needed, jerr);
    case BSER_OBJECT:
      return bunser_object(buf, end, needed, jerr);
    default:
      snprintf(jerr->text, sizeof(jerr->text),
            "invalid bser encoding type %02x", (int)buf[0]);
      return NULL;
  }

#ifndef _WIN32 // It knows this is unreachable
  return NULL;
#endif
}
Ejemplo n.º 7
0
static json_t *bunser_object(const char *buf, const char *end,
    json_int_t *used, json_error_t *jerr)
{
  json_int_t needed;
  json_int_t total = 0;
  json_int_t i, nelems;
  json_t *objval;
  char keybuf[128];

  total = 1;
  buf++;

  if (!bunser_int(buf, end - buf, &needed, &nelems)) {
    *used = needed + total;
    snprintf(jerr->text, sizeof(jerr->text),
        "invalid object property count encoding");
    return NULL;
  }

  total += needed;
  buf += needed;

  objval = json_object();
  for (i = 0; i < nelems; i++) {
    const char *start;
    json_int_t slen;
    json_t *item;

    // Read key
    if (!bunser_bytestring(buf, end - buf, &needed, &start, &slen)) {
      *used = total + needed;
      json_decref(objval);
      snprintf(jerr->text, sizeof(jerr->text),
          "invalid bytestring for object key");
      return NULL;
    }
    total += needed;
    buf += needed;

    // Saves us allocating a string when the library is going to
    // do that anyway
    if ((uint16_t)slen > sizeof(keybuf) - 1) {
      json_decref(objval);
      snprintf(jerr->text, sizeof(jerr->text),
          "object key is too long");
      return NULL;
    }
    memcpy(keybuf, start, (size_t)slen);
    keybuf[slen] = '\0';

    // Read value
    item = bunser(buf, end, &needed, jerr);
    total += needed;
    buf += needed;

    if (!item) {
      json_decref(objval);
      *used = total;
      return NULL;
    }

    if (json_object_set_new_nocheck(objval, keybuf, item)) {
      json_decref(item);
      json_decref(objval);
      *used = total;
      snprintf(jerr->text, sizeof(jerr->text),
          "failed to add object property");
      return NULL;
    }
  }

  *used = total;
  return objval;
}
Ejemplo n.º 8
0
static json_t *bunser_template(const char *buf, const char *end,
    json_int_t *used, json_error_t *jerr)
{
  json_int_t needed = 0;
  json_int_t total = 0;
  json_int_t i, nelems;
  json_int_t ip, np;
  json_t *templ = NULL, *arrval, *ret = NULL;

  buf++;
  total++;

  if (*buf != BSER_ARRAY) {
    snprintf(jerr->text, sizeof(jerr->text),
        "Expected array encoding, but found 0x%02x", *buf);
    *used = total;
    return NULL;
  }

  // Load in the property names template
  templ = bunser_array(buf, end, &needed, jerr);
  if (!templ) {
    *used = needed + total;
    goto bail;
  }
  total += needed;
  buf += needed;

  // And the number of objects
  needed = 0;
  if (!bunser_int(buf, end - buf, &needed, &nelems)) {
    *used = needed + total;
    snprintf(jerr->text, sizeof(jerr->text),
        "invalid object number encoding (needed %d but have %d)",
        (int)needed, (int)(end - buf));
    goto bail;
  }
  total += needed;
  buf += needed;

  np = json_array_size(templ);

  // Now load up the array with object values
  arrval = json_array_of_size((size_t)nelems);
  for (i = 0; i < nelems; i++) {
    json_t *item, *val;

    item = json_object_of_size((size_t)np);
    for (ip = 0; ip < np; ip++) {
      if (*buf == BSER_SKIP) {
        buf++;
        total++;
        continue;
      }

      needed = 0;
      val = bunser(buf, end, &needed, jerr);
      if (!val) {
        *used = needed + total;
        goto bail;
      }
      buf += needed;
      total += needed;

      json_object_set_new_nocheck(item,
          json_string_value(json_array_get(templ, (size_t)ip)),
          val);
    }

    json_array_append_new(arrval, item);
  }

  *used = total;
  ret = arrval;
 bail:
  json_decref(templ);
  return ret;
}