예제 #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;
}
예제 #2
0
static int
testInt( void )
{
    uint8_t         buf[128];
    int64_t         val;
    int             err;
    const uint8_t * end;

    /* good int string */
    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
    check( err == 0 );
    check( val == 64 );
    check( end == buf + 4 );

    /* missing 'e' */
    end = NULL;
    val = 888;
    err = tr_bencParseInt( buf, buf + 3, &end, &val );
    check( err == EILSEQ );
    check( val == 888 );
    check( end == NULL );

    /* empty buffer */
    err = tr_bencParseInt( buf, buf + 0, &end, &val );
    check( err == EILSEQ );
    check( val == 888 );
    check( end == NULL );

    /* bad number */
    tr_snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
    err = tr_bencParseInt( buf, buf + 5, &end, &val );
    check( err == EILSEQ );
    check( val == 888 );
    check( end == NULL );

    /* negative number */
    tr_snprintf( (char*)buf, sizeof( buf ), "i-3e" );
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
    check( err == 0 );
    check( val == -3 );
    check( end == buf + 4 );

    /* zero */
    tr_snprintf( (char*)buf, sizeof( buf ), "i0e" );
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
    check( err == 0 );
    check( val == 0 );
    check( end == buf + 3 );

    /* no leading zeroes allowed */
    val = 0;
    end = NULL;
    tr_snprintf( (char*)buf, sizeof( buf ), "i04e" );
    err = tr_bencParseInt( buf, buf + 4, &end, &val );
    check( err == EILSEQ );
    check( val == 0 );
    check( end == NULL );

    return 0;
}