Exemplo n.º 1
0
/**
 * This function's previous recursive implementation was
 * easier to read, but was vulnerable to a smash-stacking
 * attack via maliciously-crafted bencoded data. (#667)
 */
int
tr_variantParseBenc (const void    * buf_in,
                     const void    * bufend_in,
                     tr_variant    * top,
                     const char   ** setme_end)
{
  int err = 0;
  const uint8_t * buf = buf_in;
  const uint8_t * bufend = bufend_in;
  tr_ptrArray stack = TR_PTR_ARRAY_INIT;
  tr_quark key = 0;

  tr_variantInit (top, 0);

  while (buf != bufend)
    {
      if (buf > bufend) /* no more text to parse... */
        err = EILSEQ;

      if (err)
        break;

      if (*buf == 'i') /* int */
        {
          int64_t val;
          const uint8_t * end;
          tr_variant * v;

          if ((err = tr_bencParseInt (buf, bufend, &end, &val)))
            break;
          buf = end;

          if ((v = get_node (&stack, &key, top, &err)))
            tr_variantInitInt (v, val);
        }
      else if (*buf == 'l') /* list */
        {
          tr_variant * v;

          ++buf;

          if ((v = get_node (&stack, &key, top, &err)))
            {
              tr_variantInitList (v, 0);
              tr_ptrArrayAppend (&stack, v);
            }
        }
      else if (*buf == 'd') /* dict */
        {
          tr_variant * v;

          ++buf;

          if ((v = get_node (&stack, &key, top, &err)))
            {
              tr_variantInitDict (v, 0);
              tr_ptrArrayAppend (&stack, v);
            }
        }
      else if (*buf == 'e') /* end of list or dict */
        {
          ++buf;

          if (tr_ptrArrayEmpty (&stack) || (key != 0))
            {
              err = EILSEQ;
              break;
            }
          else
            {
              tr_ptrArrayPop (&stack);
              if (tr_ptrArrayEmpty (&stack))
                break;
            }
        }
      else if (isdigit (*buf)) /* string? */
        {
          tr_variant * v;
          const uint8_t * end;
          const uint8_t * str;
          size_t str_len;

          if ((err = tr_bencParseStr (buf, bufend, &end, &str, &str_len)))
            break;
          buf = end;

          if (!key && !tr_ptrArrayEmpty(&stack) && tr_variantIsDict(tr_ptrArrayBack(&stack)))
            key = tr_quark_new (str, str_len);
          else if ((v = get_node (&stack, &key, top, &err)))
            tr_variantInitStr (v, str, str_len);
        }
      else /* invalid bencoded text... march past it */
        {
          ++buf;
        }

      if (tr_ptrArrayEmpty (&stack))
        break;
    }

  if (!err && (!top->type || !tr_ptrArrayEmpty(&stack)))
    err = EILSEQ;

  if (!err && setme_end)
    *setme_end = (const char*) buf;

  tr_ptrArrayDestruct (&stack, NULL);
  return err;
}
Exemplo n.º 2
0
static int
callback( void *             vdata,
          int                type,
          const JSON_value * value )
{
    struct json_benc_data * data = vdata;
    tr_benc *               node;

    switch( type )
    {
        case JSON_T_ARRAY_BEGIN:
            node = getNode( data );
            tr_bencInitList( node, 0 );
            tr_ptrArrayAppend( data->stack, node );
            break;

        case JSON_T_ARRAY_END:
            tr_ptrArrayPop( data->stack );
            break;

        case JSON_T_OBJECT_BEGIN:
            node = getNode( data );
            tr_bencInitDict( node, 0 );
            tr_ptrArrayAppend( data->stack, node );
            break;

        case JSON_T_OBJECT_END:
            tr_ptrArrayPop( data->stack );
            break;

        case JSON_T_FLOAT:
        {
            char buf[128];
            tr_snprintf( buf, sizeof( buf ), "%f",
                         (double)value->vu.float_value );
            tr_bencInitStr( getNode( data ), buf, -1 );
            break;
        }

        case JSON_T_NULL:
            tr_bencInitStr( getNode( data ), "", 0 );
            break;

        case JSON_T_INTEGER:
            tr_bencInitInt( getNode( data ), value->vu.integer_value );
            break;

        case JSON_T_TRUE:
            tr_bencInitInt( getNode( data ), 1 );
            break;

        case JSON_T_FALSE:
            tr_bencInitInt( getNode( data ), 0 );
            break;

        case JSON_T_STRING:
            tr_bencInitStr( getNode( data ),
                            value->vu.str.value,
                            value->vu.str.length );
            break;

        case JSON_T_KEY:
            assert( !data->key );
            data->key = tr_strdup( value->vu.str.value );
            break;
    }

    return 1;
}