Changeset 4876


Ignore:
Timestamp:
Jan 31, 2008, 2:24:43 AM (14 years ago)
Author:
charles
Message:

#667: remote crash exploit in bencode parser

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/torrents.c

    r4306 r4876  
    612612timerfunc( int fd UNUSED, short event UNUSED, void * arg UNUSED )
    613613{
    614     struct tor       * tor, * next;
    615     tr_handle_status * hs;
    616     int                stillmore;
    617     struct timeval     tv;
     614    struct tor             * tor, * next;
     615    const tr_handle_status * hs;
     616    int                      stillmore;
     617    struct timeval           tv;
    618618
    619619    /* true if we've still got live torrents... */
  • trunk/gtk/ipc.c

    r4739 r4876  
    978978smsg_pref( enum ipc_msg id, benc_val_t * val UNUSED, int64_t tag, void * arg )
    979979{
    980     struct constate      * con = arg;
    981     struct constate_serv * srv = &con->u.serv;
    982     uint8_t              * buf;
    983     size_t                 size;
    984     tr_handle_status     * hstat;
    985     const char           * pref;
    986     int                    num;
     980    struct constate         * con = arg;
     981    struct constate_serv    * srv = &con->u.serv;
     982    uint8_t                 * buf;
     983    size_t                    size;
     984    const tr_handle_status  * hstat;
     985    const char              * pref;
     986    int                       num;
    987987
    988988    switch( id )
  • trunk/libtransmission/bencode-test.c

    r4869 r4876  
    44#include "utils.h" /* tr_free */
    55
    6 #define VERBOSE 1
     6#define VERBOSE 0
    77
    88int test = 0;
     
    3030    /* good int string */
    3131    snprintf( (char*)buf, sizeof( buf ), "i64e" );
    32     err = tr_bencParseInt( buf, 4, &end, &val );
     32    err = tr_bencParseInt( buf, buf+4, &end, &val );
    3333    check( err == 0 );
    3434    check( val == 64 );
     
    3838    end = NULL;
    3939    val = 888;
    40     err = tr_bencParseInt( buf, 3, &end, &val );
     40    err = tr_bencParseInt( buf, buf+3, &end, &val );
    4141    check( err == TR_ERROR );
    4242    check( val == 888 );
     
    4444
    4545    /* empty buffer */
    46     err = tr_bencParseInt( buf, 0, &end, &val );
     46    err = tr_bencParseInt( buf, buf+0, &end, &val );
    4747    check( err == TR_ERROR );
    4848    check( val == 888 );
     
    5151    /* bad number */
    5252    snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
    53     err = tr_bencParseInt( buf, 4, &end, &val );
     53    err = tr_bencParseInt( buf, buf+5, &end, &val );
    5454    check( err == TR_ERROR );
    5555    check( val == 888 );
     
    5858    /* negative number */
    5959    snprintf( (char*)buf, sizeof( buf ), "i-3e" );
    60     err = tr_bencParseInt( buf, 4, &end, &val );
     60    err = tr_bencParseInt( buf, buf+4, &end, &val );
    6161    check( err == TR_OK );
    6262    check( val == -3 );
     
    6565    /* zero */
    6666    snprintf( (char*)buf, sizeof( buf ), "i0e" );
    67     err = tr_bencParseInt( buf, 4, &end, &val );
     67    err = tr_bencParseInt( buf, buf+4, &end, &val );
    6868    check( err == TR_OK );
    6969    check( val == 0 );
     
    7474    end = NULL;
    7575    snprintf( (char*)buf, sizeof( buf ), "i04e" );
    76     err = tr_bencParseInt( buf, 4, &end, &val );
     76    err = tr_bencParseInt( buf, buf+4, &end, &val );
    7777    check( err == TR_ERROR );
    7878    check( val == 0 );
     
    9393    /* good string */
    9494    snprintf( (char*)buf, sizeof( buf ), "4:boat" );
    95     err = tr_bencParseStr( buf, 6, &end, &str, &len );
     95    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
    9696    check( err == TR_OK );
    9797    check( !strcmp( (char*)str, "boat" ) );
     
    104104
    105105    /* string goes past end of buffer */
    106     err = tr_bencParseStr( buf, 5, &end, &str, &len );
     106    err = tr_bencParseStr( buf, buf+5, &end, &str, &len );
    107107    check( err == TR_ERROR );
    108108    check( str == NULL );
     
    112112    /* empty string */
    113113    snprintf( (char*)buf, sizeof( buf ), "0:" );
    114     err = tr_bencParseStr( buf, 2, &end, &str, &len );
     114    err = tr_bencParseStr( buf, buf+2, &end, &str, &len );
    115115    check( err == TR_OK );
    116116    check( !*str );
     
    124124    /* short string */
    125125    snprintf( (char*)buf, sizeof( buf ), "3:boat" );
    126     err = tr_bencParseStr( buf, 6, &end, &str, &len );
     126    err = tr_bencParseStr( buf, buf+6, &end, &str, &len );
    127127    check( err == TR_OK );
    128128    check( !strcmp( (char*)str, "boa" ) );
     
    136136    return 0;
    137137}
    138  
     138
     139static int
     140testParse( void )
     141{
     142    benc_val_t val;
     143    benc_val_t * child;
     144    benc_val_t * child2;
     145    uint8_t buf[512];
     146    const uint8_t * end;
     147    int err;
     148    int len;
     149    char * saved;
     150
     151    snprintf( (char*)buf, sizeof( buf ), "i64e" );
     152    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
     153    check( !err );
     154    check( tr_bencIsInt( &val ) );
     155    check( tr_bencGetInt( &val ) == 64 );
     156    check( end == buf + 4 );
     157    tr_bencFree( &val );
     158
     159    snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
     160    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
     161    check( !err );
     162    check( tr_bencIsList( &val ) );
     163    check( end == buf + strlen( (char*)buf ) );
     164    check( val.val.l.count == 3 );
     165    check( tr_bencGetInt( &val.val.l.vals[0] ) == 64 );
     166    check( tr_bencGetInt( &val.val.l.vals[1] ) == 32 );
     167    check( tr_bencGetInt( &val.val.l.vals[2] ) == 16 );
     168    saved = tr_bencSave( &val, &len );
     169    check( !strcmp( saved, (char*)buf ) );
     170    tr_free( saved );
     171    tr_bencFree( &val );
     172
     173    end = NULL;
     174    snprintf( (char*)buf, sizeof( buf ), "lllee" );
     175    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val , &end );
     176    check( err );
     177    check( end == NULL );
     178
     179    end = NULL;
     180    snprintf( (char*)buf, sizeof( buf ), "le" );
     181    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
     182    check( !err );
     183    check( end == buf + 2 );
     184    saved = tr_bencSave( &val, &len );
     185    check( !strcmp( saved, "le" ) );
     186    tr_free( saved );
     187    tr_bencFree( &val );
     188
     189    end = NULL;
     190    snprintf( (char*)buf, sizeof( buf ), "llleee" );
     191    err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
     192    check( !err );
     193    check( end == buf + 6 );
     194    saved = tr_bencSave( &val, &len );
     195    check( !strcmp( saved, "llleee" ) );
     196    tr_free( saved );
     197    tr_bencFree( &val );
     198
     199    /* nested containers
     200     * parse an unsorted dict
     201     * save as a sorted dict */
     202    end = NULL;
     203    snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
     204    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
     205    check( !err );
     206    check( end == buf + strlen( (const char*)buf ) );
     207    check( tr_bencIsList( &val ) );
     208    check(( child = tr_bencListGetNthChild( &val, 0 )));
     209    check( tr_bencIsList( child ) );
     210    check(( child2 = tr_bencListGetNthChild( child, 0 )));
     211    check( tr_bencIsDict( child2 ) );
     212    saved = tr_bencSave( &val, &len );
     213    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
     214    tr_free( saved );
     215    tr_bencFree( &val );
     216
     217    return 0;
     218}
     219
     220static int
     221testStackSmash( void )
     222{
     223    int i;
     224    int len;
     225    int depth;
     226    int err;
     227    uint8_t * in;
     228    const uint8_t * end;
     229    benc_val_t val;
     230    char * saved;
     231
     232    depth = 1000000;
     233    in = tr_new( uint8_t, depth*2 + 1 );
     234    for( i=0; i<depth; ++i ) {
     235        in[i] = 'l';
     236        in[depth+i] = 'e';
     237    }
     238    in[depth*2] = '\0';
     239    err = tr_bencParse( in, in+(depth*2), &val, &end );
     240    check( !err );
     241    check( tr_bencIsList( &val ) );
     242    check( end == in+(depth*2) );
     243    saved = tr_bencSave( &val, &len );
     244    check( !strcmp( saved, (char*)in ) );
     245    tr_free( in );
     246    tr_free( saved );
     247    tr_bencFree( &val );
     248
     249    return 0;
     250}
     251
     252
    139253int
    140254main( void )
     
    142256    int i;
    143257
    144     if(( i = testInt( ) ))
    145         return i;
    146 
    147     if(( i = testStr( ) ))
    148         return i;
    149 
    150     return 0;
    151 }
     258    if(( i = testInt( )))
     259        return i;
     260
     261    if(( i = testStr( )))
     262        return i;
     263
     264    if(( i = testParse( )))
     265        return i;
     266
     267    if(( i = testStackSmash( )))
     268        return i;
     269
     270    return 0;
     271}
  • trunk/libtransmission/bencode.c

    r4869 r4876  
    3434#include "transmission.h"
    3535#include "bencode.h"
     36#include "ptrarray.h"
    3637#include "utils.h"
    3738
     
    4041**/
    4142
     43int
     44tr_bencIsInt( const benc_val_t * val )
     45{
     46    return val!=NULL && val->type==TYPE_INT;
     47}
     48
     49int
     50tr_bencIsString( const benc_val_t * val )
     51{
     52    return val!=NULL && val->type==TYPE_STR;
     53}
     54
     55int
     56tr_bencIsList( const benc_val_t * val )
     57{
     58    return val!=NULL && val->type==TYPE_LIST;
     59}
     60
     61int
     62tr_bencIsDict( const benc_val_t * val )
     63{
     64    return val!=NULL && val->type==TYPE_DICT;
     65}
     66
    4267static int
    43 tr_bencIsInt ( const benc_val_t * val ) {
    44     return val!=NULL && val->type==TYPE_INT;
    45 }
    46 
    47 static int
    48 tr_bencIsList( const benc_val_t * val ) {
    49     return val!=NULL && val->type==TYPE_LIST;
    50 }
    51 
    52 static int
    53 tr_bencIsDict( const benc_val_t * val ) {
    54     return val!=NULL && val->type==TYPE_DICT;
    55 }
     68isContainer( const benc_val_t * val )
     69{
     70    return val!=NULL && ( val->type & ( TYPE_DICT | TYPE_LIST ) );
     71}
     72
     73benc_val_t*
     74tr_bencListGetNthChild( benc_val_t * val, int i )
     75{
     76    benc_val_t * ret = NULL;
     77    if( tr_bencIsList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
     78        ret = val->val.l.vals + i;
     79    return ret;
     80}
     81
    5682
    5783/**
     
    7096int
    7197tr_bencParseInt( const uint8_t  * buf,
    72                  size_t           buflen,
     98                 const uint8_t  * bufend,
    7399                 const uint8_t ** setme_end,
    74100                 int64_t        * setme_val )
     
    80106    int64_t val;
    81107
    82     if( !buflen )
     108    if( buf >= bufend )
    83109        return TR_ERROR;
    84110    if( *buf != 'i' )
     
    86112
    87113    begin = buf + 1;
    88     end = memchr( begin, 'e', buflen-1 );
     114    end = memchr( begin, 'e', (bufend-buf)-1 );
    89115    if( end == NULL )
    90116        return TR_ERROR;
     
    113139int
    114140tr_bencParseStr( const uint8_t  * buf,
    115                  size_t           buflen,
     141                 const uint8_t  * bufend,
    116142                 const uint8_t ** setme_end,
    117143                 uint8_t       ** setme_str,
     
    122148    char * endptr;
    123149
    124     if( !buflen )
     150    if( buf >= bufend )
    125151        return TR_ERROR;
    126152
     
    128154        return TR_ERROR;
    129155
    130     end = memchr( buf, ':', buflen );
     156    end = memchr( buf, ':', bufend-buf );
    131157    if( end == NULL )
    132158        return TR_ERROR;
     
    137163        return TR_ERROR;
    138164
    139     if( ( (const uint8_t*)end - buf ) + 1 + len > buflen )
     165    if( (const uint8_t*)end + 1 + len > bufend )
    140166        return TR_ERROR;
    141167
     
    147173
    148174/* setting to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
    149 #define LIST_SIZE   20 /* number of items to increment list/dict buffer by */
    150 
    151 static int makeroom( benc_val_t * val, int count )
     175#define LIST_SIZE 8 /* number of items to increment list/dict buffer by */
     176
     177static int
     178makeroom( benc_val_t * val, int count )
    152179{
    153180    assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
     
    169196}
    170197
    171 int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
    172 {
    173     char * p, * e, * foo;
    174 
    175     if( !end )
    176     {
    177         /* So we only have to check once */
    178         end = &foo;
    179     }
    180 
    181     for( ;; )
    182     {
    183         if( !buf || len<1 ) /* no more text to parse... */
     198static benc_val_t*
     199getNode( benc_val_t * top, tr_ptrArray * parentStack, int type )
     200{
     201    benc_val_t * parent;
     202
     203    assert( top != NULL );
     204    assert( parentStack != NULL );
     205
     206    if( tr_ptrArrayEmpty( parentStack ) )
     207        return top;
     208
     209    parent = tr_ptrArrayBack( parentStack );
     210    assert( parent != NULL );
     211
     212    /* dictionary keys must be strings */
     213    if( ( parent->type == TYPE_DICT )
     214        && ( type != TYPE_STR )
     215        && ( ! ( parent->val.l.count % 2 ) ) )
     216        return NULL;
     217
     218    makeroom( parent, 1 );
     219    return parent->val.l.vals + parent->val.l.count++;
     220}
     221
     222/**
     223 * this function's awkward stack-based implementation
     224 * is to prevent maliciously-crafed bencode data from
     225 * smashing our stack through deep recursion. (#667)
     226 */
     227int
     228tr_bencParse( const void  * buf_in,
     229              const void  * bufend_in,
     230              benc_val_t     * top,
     231              const uint8_t ** setme_end )
     232{
     233    int err;
     234    const uint8_t * buf = buf_in;
     235    const uint8_t * bufend = bufend_in;
     236    tr_ptrArray * parentStack = tr_ptrArrayNew( );
     237
     238    while( buf != bufend )
     239    {
     240        if( buf > bufend ) /* no more text to parse... */
    184241            return 1;
    185242
    186         if( *buf=='i' ) /* Integer: i1234e */
    187         {
    188             int64_t num;
    189 
    190             e = memchr( &buf[1], 'e', len - 1 );
    191             if( !e )
    192                 return 1;
    193 
    194             *e = '\0';
    195             num = strtoll( &buf[1], &p, 10 );
    196             *e = 'e';
    197 
    198             if( p != e )
    199                 return 1;
    200 
    201             tr_bencInitInt( val, num );
    202             *end = p + 1;
    203             break;
    204         }
    205         else if( *buf=='l' || *buf=='d' )
    206         {
    207             /* List: l<item1><item2>e
    208                Dict: d<string1><item1><string2><item2>e
    209                A dictionary is just a special kind of list with an even
    210                count of items, and where even items are strings. */
    211             char * cur;
    212             char   is_dict;
    213             char   str_expected;
    214 
    215             is_dict      = ( buf[0] == 'd' );
    216             cur          = &buf[1];
    217             str_expected = 1;
    218             tr_bencInit( val, ( is_dict ? TYPE_DICT : TYPE_LIST ) );
    219             while( cur - buf < len && cur[0] != 'e' )
    220             {
    221                 if( makeroom( val, 1 ) ||
    222                     tr_bencLoad( cur, len - (cur - buf),
    223                                  &val->val.l.vals[val->val.l.count], &p ) )
    224                 {
    225                     tr_bencFree( val );
    226                     return 1;
    227                 }
    228                 val->val.l.count++;
    229                 if( is_dict && str_expected &&
    230                     val->val.l.vals[val->val.l.count - 1].type != TYPE_STR )
    231                 {
    232                     tr_bencFree( val );
    233                     return 1;
    234                 }
    235                 str_expected = !str_expected;
    236 
    237                 cur = p;
    238             }
    239 
    240             if( is_dict && ( val->val.l.count & 1 ) )
    241             {
    242                 tr_bencFree( val );
    243                 return 1;
    244             }
    245 
    246             *end = cur + 1;
    247             break;
    248         }
    249         else if( isdigit(*buf) )
    250         {
    251             int    slen;
    252             char * sbuf;
    253 
    254             e = memchr( buf, ':', len );
    255             if( NULL == e )
    256             {
    257                 return 1;
    258             }
    259 
    260             /* String: 12:whateverword */
    261             e[0] = '\0';
    262             slen = strtol( buf, &p, 10 );
    263             e[0] = ':';
    264 
    265             if( p != e || 0 > slen || len - ( ( p + 1 ) - buf ) < slen )
    266             {
    267                 return 1;
    268             }
    269 
    270             sbuf = malloc( slen + 1 );
    271             if( NULL == sbuf )
    272             {
    273                 return 1;
    274             }
    275 
    276             memcpy( sbuf, p + 1, slen );
    277             sbuf[slen] = '\0';
    278             tr_bencInitStr( val, sbuf, slen, 0 );
    279 
    280             *end = p + 1 + val->val.s.i;
    281             break;
     243        if( *buf=='i' ) /* int */
     244        {
     245            int64_t val;
     246            const uint8_t * end;
     247            int err;
     248            benc_val_t * node;
     249
     250            if(( err = tr_bencParseInt( (const uint8_t*)buf, bufend, &end, &val )))
     251                return err;
     252
     253            node = getNode( top, parentStack, TYPE_INT );
     254            if( !node )
     255                return TR_ERROR;
     256
     257            tr_bencInitInt( node, val );
     258            buf = end;
     259
     260            if( tr_ptrArrayEmpty( parentStack ) )
     261                break;
     262        }
     263        else if( *buf=='l' ) /* list */
     264        {
     265            benc_val_t * node = getNode( top, parentStack, TYPE_LIST );
     266            if( !node )
     267                return TR_ERROR;
     268            tr_bencInit( node, TYPE_LIST );
     269            tr_ptrArrayAppend( parentStack, node );
     270            ++buf;
     271        }
     272        else if( *buf=='d' ) /* dict */
     273        {
     274            benc_val_t * node = getNode( top, parentStack, TYPE_DICT );
     275            if( !node )
     276                return TR_ERROR;
     277            tr_bencInit( node, TYPE_DICT );
     278            tr_ptrArrayAppend( parentStack, node );
     279            ++buf;
     280        }
     281        else if( *buf=='e' ) /* end of list or dict */
     282        {
     283            ++buf;
     284            if( tr_ptrArrayEmpty( parentStack ) )
     285                return TR_ERROR;
     286            tr_ptrArrayPop( parentStack );
     287            if( tr_ptrArrayEmpty( parentStack ) )
     288                break;
     289        }
     290        else if( isdigit(*buf) ) /* string? */
     291        {
     292            const uint8_t * end;
     293            uint8_t * str;
     294            size_t strlen;
     295            int err;
     296            benc_val_t * node;
     297
     298            if(( err = tr_bencParseStr( buf, bufend, &end, &str, &strlen )))
     299                return err;
     300
     301            node = getNode( top, parentStack, TYPE_STR );
     302            if( !node )
     303                return TR_ERROR;
     304
     305            tr_bencInitStr( node, str, strlen, 0 );
     306            buf = end;
     307
     308            if( tr_ptrArrayEmpty( parentStack ) )
     309                break;
    282310        }
    283311        else /* invalid bencoded text... march past it */
    284312        {
    285313            ++buf;
    286             --len;
    287         }
    288     }
    289 
    290     return 0;
    291 }
    292 
    293 static void __bencPrint( benc_val_t * val, int space )
    294 {
    295     int ii;
    296 
    297     for( ii = 0; ii < space; ii++ )
    298     {
    299         putc( ' ', stderr );
    300     }
    301 
    302     switch( val->type )
    303     {
    304         case TYPE_INT:
    305             fprintf( stderr, "int:  %"PRId64"\n", tr_bencGetInt(val) );
    306             break;
    307 
    308         case TYPE_STR:
    309             for( ii = 0; val->val.s.i > ii; ii++ )
    310             {
    311                 if( '\\' == val->val.s.s[ii] )
    312                 {
    313                     putc( '\\', stderr );
    314                     putc( '\\', stderr );
    315                 }
    316                 else if( isprint( val->val.s.s[ii] ) )
    317                 {
    318                     putc( val->val.s.s[ii], stderr );
    319                 }
    320                 else
    321                 {
    322                     fprintf( stderr, "\\x%02x", val->val.s.s[ii] );
    323                 }
    324             }
    325             putc( '\n', stderr );
    326             break;
    327 
    328         case TYPE_LIST:
    329             fprintf( stderr, "list\n" );
    330             for( ii = 0; ii < val->val.l.count; ii++ )
    331             {
    332                 __bencPrint( &val->val.l.vals[ii], space + 1 );
    333             }
    334             break;
    335 
    336         case TYPE_DICT:
    337             fprintf( stderr, "dict\n" );
    338             for( ii = 0; ii < val->val.l.count; ii++ )
    339             {
    340                 __bencPrint( &val->val.l.vals[ii], space + 1 );
    341             }
    342             break;
    343     }
    344 }
    345 
    346 void tr_bencPrint( benc_val_t * val )
    347 {
    348     __bencPrint( val, 0 );
    349 }
    350 
    351 void tr_bencFree( benc_val_t * val )
    352 {
    353     int i;
    354 
    355     switch( val->type )
    356     {
    357         case TYPE_INT:
    358             break;
    359 
    360         case TYPE_STR:
    361             if( !val->val.s.nofree )
    362             {
    363                 free( val->val.s.s );
    364             }
    365             break;
    366 
    367         case TYPE_LIST:
    368         case TYPE_DICT:
    369             for( i = 0; i < val->val.l.count; i++ )
    370             {
    371                 tr_bencFree( &val->val.l.vals[i] );
    372             }
    373             free( val->val.l.vals );
    374             break;
    375     }
    376 }
    377 
    378 benc_val_t * tr_bencDictFind( benc_val_t * val, const char * key )
     314        }
     315    }
     316
     317    err = tr_ptrArrayEmpty( parentStack ) ? 0 : 1;
     318
     319    if( !err && ( setme_end != NULL ) )
     320        *setme_end = buf;
     321
     322    tr_ptrArrayFree( parentStack, NULL );
     323    return err;
     324}
     325
     326int
     327tr_bencLoad( const void  * buf_in,
     328             int           buflen,
     329             benc_val_t  * setme_benc,
     330             char       ** setme_end )
     331{
     332    const uint8_t * buf = buf_in;
     333    const uint8_t * end;
     334    const int ret = tr_bencParse( buf, buf+buflen, setme_benc, &end );
     335    if( !ret && setme_end )
     336        *setme_end = (char*) end;
     337    return ret;
     338}
     339
     340benc_val_t *
     341tr_bencDictFind( benc_val_t * val, const char * key )
    379342{
    380343    int len, ii;
     
    401364}
    402365
    403 benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... )
     366benc_val_t*
     367tr_bencDictFindType( benc_val_t * val, const char * key, int type )
     368{
     369    benc_val_t * ret = tr_bencDictFind( val, key );
     370    return ret && ret->type == type ? ret : NULL;
     371}
     372
     373int64_t
     374tr_bencGetInt ( const benc_val_t * val )
     375{
     376    assert( tr_bencIsInt( val ) );
     377    return val->val.i;
     378}
     379
     380benc_val_t *
     381tr_bencDictFindFirst( benc_val_t * val, ... )
    404382{
    405383    const char * key;
     
    422400}
    423401
    424 char * tr_bencStealStr( benc_val_t * val )
     402char *
     403tr_bencStealStr( benc_val_t * val )
    425404{
    426405    assert( TYPE_STR == val->type );
     
    429408}
    430409
    431 void _tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree )
     410void
     411_tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree )
    432412{
    433413    tr_bencInit( val, TYPE_STR );
     
    441421}
    442422
    443 int tr_bencInitStrDup( benc_val_t * val, const char * str )
     423int
     424tr_bencInitStrDup( benc_val_t * val, const char * str )
    444425{
    445426    char * newStr = tr_strdup( str );
     
    451432}
    452433
    453 void tr_bencInitInt( benc_val_t * val, int64_t num )
     434void
     435tr_bencInitInt( benc_val_t * val, int64_t num )
    454436{
    455437    tr_bencInit( val, TYPE_INT );
     
    457439}
    458440
    459 int tr_bencListReserve( benc_val_t * val, int count )
     441int
     442tr_bencListReserve( benc_val_t * val, int count )
    460443{
    461444    assert( TYPE_LIST == val->type );
     
    464447}
    465448
    466 int tr_bencDictReserve( benc_val_t * val, int count )
     449int
     450tr_bencDictReserve( benc_val_t * val, int count )
    467451{
    468452    assert( TYPE_DICT == val->type );
     
    471455}
    472456
    473 benc_val_t * tr_bencListAdd( benc_val_t * list )
     457benc_val_t *
     458tr_bencListAdd( benc_val_t * list )
    474459{
    475460    benc_val_t * item;
     
    485470}
    486471
    487 benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key )
     472benc_val_t *
     473tr_bencDictAdd( benc_val_t * dict, const char * key )
    488474{
    489475    benc_val_t * keyval, * itemval;
     
    500486    return itemval;
    501487}
     488
     489
     490/***
     491****  BENC WALKING
     492***/
    502493
    503494struct KeyIndex
     
    507498};
    508499
    509 static int compareKeyIndex( const void * va, const void * vb )
     500static int
     501compareKeyIndex( const void * va, const void * vb )
    510502{
    511503    const struct KeyIndex * a = va;
     
    514506}
    515507
    516 static void
    517 saveImpl( struct evbuffer * out, const benc_val_t * val )
     508struct SaveNode
     509{
     510    const benc_val_t * val;
     511    int valIsSaved;
     512    int childCount;
     513    int childIndex;
     514    int * children;
     515};
     516
     517static struct SaveNode*
     518nodeNewDict( const benc_val_t * val )
     519{
     520    int i, j, n;
     521    struct SaveNode * node;
     522    struct KeyIndex * indices;
     523
     524    assert( tr_bencIsDict( val ) );
     525
     526    n = val->val.l.count;
     527    node = tr_new0( struct SaveNode, 1 );
     528    node->val = val;
     529    node->children = tr_new0( int, n );
     530
     531    /* ugh, a dictionary's children have to be sorted by key... */
     532    indices = tr_new( struct KeyIndex, n );
     533    for( i=j=0; i<n; i+=2, ++j ) {
     534        indices[j].key = val->val.l.vals[i].val.s.s;
     535        indices[j].index = i;
     536    }
     537    qsort( indices, j, sizeof(struct KeyIndex), compareKeyIndex );
     538    for( i=0; i<j; ++i ) {
     539        const int index = indices[i].index;
     540        node->children[ node->childCount++ ] = index;
     541        node->children[ node->childCount++ ] = index + 1;
     542    }
     543
     544    assert( node->childCount == n );
     545    tr_free( indices );
     546    return node;
     547}
     548
     549static struct SaveNode*
     550nodeNewList( const benc_val_t * val )
     551{
     552    int i, n;
     553    struct SaveNode * node;
     554
     555    assert( tr_bencIsList( val ) );
     556
     557    n = val->val.l.count;
     558    node = tr_new0( struct SaveNode, 1 );
     559    node->val = val;
     560    node->childCount = n;
     561    node->children = tr_new0( int, n );
     562    for( i=0; i<n; ++i ) /* a list's children don't need to be reordered */
     563        node->children[i] = i;
     564
     565    return node;
     566}
     567
     568static struct SaveNode*
     569nodeNewSimple( const benc_val_t * val )
     570{
     571    struct SaveNode * node;
     572
     573    assert( !isContainer( val ) );
     574
     575    node = tr_new0( struct SaveNode, 1 );
     576    node->val = val;
     577    return node;
     578}
     579
     580static struct SaveNode*
     581nodeNew( const benc_val_t * val )
     582{
     583    switch( val->type )
     584    {
     585        case TYPE_INT:
     586        case TYPE_STR:
     587            return nodeNewSimple( val );
     588            break;
     589        case TYPE_LIST:
     590            return nodeNewList( val );
     591            break;
     592        case TYPE_DICT:
     593            return nodeNewDict( val );
     594            break;
     595    }
     596
     597    assert( 0 && "invalid type!" );
     598    return NULL;
     599}
     600
     601typedef void (*BencNodeWalkFunc)( const benc_val_t * val, void * user_data );
     602
     603struct WalkFuncs
     604{
     605    BencNodeWalkFunc intFunc;
     606    BencNodeWalkFunc stringFunc;
     607    BencNodeWalkFunc dictBeginFunc;
     608    BencNodeWalkFunc listBeginFunc;
     609    BencNodeWalkFunc containerEndFunc;
     610};
     611
     612/**
     613 * this function's awkward stack-based implementation
     614 * is to prevent maliciously-crafed bencode data from
     615 * smashing our stack through deep recursion. (#667)
     616 */
     617static void
     618depthFirstWalk( const benc_val_t * top, struct WalkFuncs * walkFuncs, void * user_data )
     619{
     620    tr_ptrArray * stack = tr_ptrArrayNew( );
     621    tr_ptrArrayAppend( stack, nodeNew( top ) );
     622
     623    while( !tr_ptrArrayEmpty( stack ) )
     624    {
     625        struct SaveNode * node = tr_ptrArrayBack( stack );
     626        const benc_val_t * val;
     627
     628        if( !node->valIsSaved )
     629        {
     630            val = node->val;
     631            node->valIsSaved = TRUE;
     632        }
     633        else if( node->childIndex < node->childCount )
     634        {
     635            const int index = node->children[ node->childIndex++ ];
     636            val = node->val->val.l.vals +  index;
     637        }
     638        else /* done with this node */
     639        {
     640            if( isContainer( node->val ) )
     641                walkFuncs->containerEndFunc( node->val, user_data );
     642            tr_ptrArrayPop( stack );
     643            tr_free( node->children );
     644            tr_free( node );
     645            continue;
     646        }
     647
     648        switch( val->type )
     649        {
     650            case TYPE_INT:
     651                walkFuncs->intFunc( val, user_data );
     652                break;
     653
     654            case TYPE_STR:
     655                walkFuncs->stringFunc( val, user_data );
     656                break;
     657
     658            case TYPE_LIST:
     659                if( val != node->val )
     660                    tr_ptrArrayAppend( stack, nodeNew( val ) );
     661                else
     662                    walkFuncs->listBeginFunc( val, user_data );
     663                break;
     664
     665            case TYPE_DICT:
     666                if( val != node->val )
     667                    tr_ptrArrayAppend( stack, nodeNew( val ) );
     668                else
     669                    walkFuncs->dictBeginFunc( val, user_data );
     670                break;
     671
     672            default:
     673                assert( 0 && "invalid type!" );
     674        }
     675    }
     676
     677    tr_ptrArrayFree( stack, NULL );
     678}
     679
     680/****
     681*****
     682****/
     683
     684static void
     685saveIntFunc( const benc_val_t * val, void * buf )
     686{
     687    evbuffer_add_printf( buf, "i%"PRId64"e", tr_bencGetInt(val) );
     688}
     689static void
     690saveStringFunc( const benc_val_t * val, void * user_data )
     691{
     692    struct evbuffer * out = user_data;
     693    evbuffer_add_printf( out, "%i:", val->val.s.i );
     694    evbuffer_add( out, val->val.s.s, val->val.s.i );
     695}
     696static void
     697saveDictBeginFunc( const benc_val_t * val UNUSED, void * buf )
     698{
     699    evbuffer_add_printf( buf, "d" );
     700}
     701static void
     702saveListBeginFunc( const benc_val_t * val UNUSED, void * buf )
     703{
     704    evbuffer_add_printf( buf, "l" );
     705}
     706static void
     707saveContainerEndFunc( const benc_val_t * val UNUSED, void * buf )
     708{
     709    evbuffer_add_printf( buf, "e" );
     710}
     711char*
     712tr_bencSave( const benc_val_t * top, int * len )
     713{
     714    char * ret;
     715    struct WalkFuncs walkFuncs;
     716    struct evbuffer * out = evbuffer_new( );
     717
     718    walkFuncs.intFunc = saveIntFunc;
     719    walkFuncs.stringFunc = saveStringFunc;
     720    walkFuncs.dictBeginFunc = saveDictBeginFunc;
     721    walkFuncs.listBeginFunc = saveListBeginFunc;
     722    walkFuncs.containerEndFunc = saveContainerEndFunc;
     723
     724    depthFirstWalk( top, &walkFuncs, out );
     725   
     726    if( len != NULL )
     727        *len = EVBUFFER_LENGTH( out );
     728    ret = tr_strndup( (char*) EVBUFFER_DATA( out ), EVBUFFER_LENGTH( out ) );
     729    evbuffer_free( out );
     730    return ret;
     731}
     732
     733/***
     734****
     735***/
     736
     737static void
     738freeDummyFunc( const benc_val_t * val UNUSED, void * buf UNUSED  )
     739{
     740}
     741static void
     742freeStringFunc( const benc_val_t * val, void * freeme )
     743{
     744    if( !val->val.s.nofree )
     745        tr_ptrArrayAppend( freeme, val->val.s.s );
     746}
     747static void
     748freeContainerBeginFunc( const benc_val_t * val, void * freeme )
     749{
     750    tr_ptrArrayAppend( freeme, val->val.l.vals );
     751}
     752void
     753tr_bencFree( benc_val_t * val )
     754{
     755    if( val != NULL )
     756    {
     757        tr_ptrArray * freeme = tr_ptrArrayNew( );
     758        struct WalkFuncs walkFuncs;
     759
     760        walkFuncs.intFunc = freeDummyFunc;
     761        walkFuncs.stringFunc = freeStringFunc;
     762        walkFuncs.dictBeginFunc = freeContainerBeginFunc;
     763        walkFuncs.listBeginFunc = freeContainerBeginFunc;
     764        walkFuncs.containerEndFunc = freeDummyFunc;
     765        depthFirstWalk( val, &walkFuncs, freeme );
     766
     767        tr_ptrArrayFree( freeme, tr_free );
     768    }
     769}
     770
     771/***
     772****
     773***/
     774
     775struct WalkPrint
     776{
     777    int depth;
     778    FILE * out;
     779};
     780static void
     781printLeadingSpaces( struct WalkPrint * data )
     782{
     783    const int width = data->depth * 2;
     784    fprintf( data->out, "%*.*s", width, width, " " );
     785}
     786static void
     787printIntFunc( const benc_val_t * val, void * vdata )
     788{
     789    struct WalkPrint * data = vdata;
     790    printLeadingSpaces( data );
     791    fprintf( data->out, "int:  %"PRId64"\n", tr_bencGetInt(val) );
     792}
     793static void
     794printStringFunc( const benc_val_t * val, void * vdata )
    518795{
    519796    int ii;
    520 
    521     switch( val->type )
    522     {
    523         case TYPE_INT:
    524             evbuffer_add_printf( out, "i%"PRId64"e", tr_bencGetInt(val) );
    525             break;
    526 
    527         case TYPE_STR:
    528             evbuffer_add_printf( out, "%i:", val->val.s.i );
    529             evbuffer_add( out, val->val.s.s, val->val.s.i );
    530             break;
    531 
    532         case TYPE_LIST:
    533             evbuffer_add_printf( out, "l" );
    534             for( ii = 0; val->val.l.count > ii; ii++ )
    535                 saveImpl( out, val->val.l.vals + ii );
    536             evbuffer_add_printf( out, "e" );
    537             break;
    538 
    539         case TYPE_DICT:
    540             /* Keys must be strings and appear in sorted order
    541                (sorted as raw strings, not alphanumerics). */
    542             evbuffer_add_printf( out, "d" );
    543             if( 1 ) {
    544                 int i;
    545                 struct KeyIndex * indices = tr_new( struct KeyIndex, val->val.l.count );
    546                 for( ii=i=0; i<val->val.l.count; i+=2 ) {
    547                     indices[ii].key = val->val.l.vals[i].val.s.s;
    548                     indices[ii].index = i;
    549                     ii++;
    550                 }
    551                 qsort( indices, ii, sizeof(struct KeyIndex), compareKeyIndex );
    552                 for( i=0; i<ii; ++i ) {
    553                     const int index = indices[i].index;
    554                     saveImpl( out, val->val.l.vals + index );
    555                     saveImpl( out, val->val.l.vals + index + 1 );
    556                 }
    557                 tr_free( indices );
    558             }
    559             evbuffer_add_printf( out, "e" );
    560             break;
    561     }
    562 }
    563 
    564 char*
    565 tr_bencSave( const benc_val_t * val, int * len )
    566 {
    567     struct evbuffer * buf = evbuffer_new( );
    568     char * ret;
    569     saveImpl( buf, val );
    570     if( len != NULL )
    571         *len = EVBUFFER_LENGTH( buf );
    572     ret = tr_strndup( (char*) EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
    573     evbuffer_free( buf );
    574     return ret;
    575 }
    576 
    577 /**
    578 ***
    579 **/
    580 
    581 benc_val_t*
    582 tr_bencDictFindType( benc_val_t * val, const char * key, int type )
    583 {
    584     benc_val_t * ret = tr_bencDictFind( val, key );
    585     return ret && ret->type == type ? ret : NULL;
    586 }
    587 
    588 int64_t
    589 tr_bencGetInt ( const benc_val_t * val )
    590 {
    591     assert( tr_bencIsInt( val ) );
    592     return val->val.i;
    593 }
     797    struct WalkPrint * data = vdata;
     798    printLeadingSpaces( data );
     799    for( ii = 0; val->val.s.i > ii; ii++ )
     800    {
     801        if( '\\' == val->val.s.s[ii] ) {
     802            putc( '\\', data->out );
     803            putc( '\\', data->out );
     804        } else if( isprint( val->val.s.s[ii] ) ) {
     805            putc( val->val.s.s[ii], data->out );
     806        } else {
     807            fprintf( data->out, "\\x%02x", val->val.s.s[ii] );
     808        }
     809    }
     810}
     811static void
     812printListBeginFunc( const benc_val_t * val UNUSED, void * vdata )
     813{
     814    struct WalkPrint * data = vdata;
     815    printLeadingSpaces( data );
     816    fprintf( data->out, "list\n" );
     817    ++data->depth;
     818}
     819static void
     820printDictBeginFunc( const benc_val_t * val UNUSED, void * vdata )
     821{
     822    struct WalkPrint * data = vdata;
     823    printLeadingSpaces( data );
     824    fprintf( data->out, "dict\n" );
     825    ++data->depth;
     826}
     827static void
     828printContainerEndFunc( const benc_val_t * val UNUSED, void * vdata )
     829{
     830    struct WalkPrint * data = vdata;
     831    --data->depth;
     832}
     833void
     834tr_bencPrint( benc_val_t * val )
     835{
     836    struct WalkFuncs walkFuncs;
     837    struct WalkPrint walkPrint;
     838
     839    walkFuncs.intFunc = printIntFunc;
     840    walkFuncs.stringFunc = printStringFunc;
     841    walkFuncs.dictBeginFunc = printDictBeginFunc;
     842    walkFuncs.listBeginFunc = printListBeginFunc;
     843    walkFuncs.containerEndFunc = printContainerEndFunc;
     844
     845    walkPrint.out = stderr;
     846    walkPrint.depth = 0;
     847    depthFirstWalk( val, &walkFuncs, &walkPrint );
     848}
  • trunk/libtransmission/bencode.h

    r4869 r4876  
    4747        struct
    4848        {
    49             int                 alloc;
    50             int                 count;
     49            int alloc;
     50            int count;
    5151            struct benc_val_s * vals;
    5252        } l;
     
    5555
    5656
    57 #define tr_bencLoad(b,l,v,e) _tr_bencLoad((char*)(b),(l),(v),(char**)(e))
    58 int          _tr_bencLoad( char * buf, int len, benc_val_t * val,
    59                            char ** end );
     57int          tr_bencParse( const void      * buf,
     58                           const void      * bufend,
     59                           benc_val_t      * setme_benc,
     60                           const uint8_t  ** setme_end );
     61
     62int          tr_bencLoad( const void  * buf,
     63                          int           buflen,
     64                          benc_val_t  * setme_benc,
     65                          char       ** setme_end );
     66
    6067void         tr_bencPrint( benc_val_t * val );
    6168void         tr_bencFree( benc_val_t * val );
     
    98105
    99106int  tr_bencParseInt( const uint8_t  * buf,
    100                       size_t           buflen,
     107                      const uint8_t  * bufend,
    101108                      const uint8_t ** setme_end,
    102109                      int64_t        * setme_val );
    103110
    104111int  tr_bencParseStr( const uint8_t  * buf,
    105                       size_t           buflen,
     112                      const uint8_t  * bufend,
    106113                      const uint8_t ** setme_end,
    107114                      uint8_t       ** setme_str,
    108115                      size_t         * setme_strlen );
    109116
     117/**
     118***
     119**/
     120
     121int tr_bencIsInt( const benc_val_t * val );
     122int tr_bencIsList( const benc_val_t * val );
     123int tr_bencIsDict( const benc_val_t * val );
     124int tr_bencIsString( const benc_val_t * val );
     125
     126benc_val_t* tr_bencListGetNthChild( benc_val_t * val, int i );
     127
     128
    110129
    111130
  • trunk/libtransmission/ptrarray.c

    r4404 r4876  
    9797}
    9898
     99void*
     100tr_ptrArrayBack( tr_ptrArray* t )
     101{
     102    assert( t->n_items > 0 );
     103
     104    return tr_ptrArrayNth( t, t->n_items-1 );
     105}
     106
    99107int
    100108tr_ptrArraySize( const tr_ptrArray * t )
     
    139147{
    140148    return tr_ptrArrayInsert( t, ptr, -1 );
     149}
     150
     151void*
     152tr_ptrArrayPop( tr_ptrArray* t )
     153{
     154    void * ret = NULL;
     155
     156    if( t->n_items )
     157        ret = t->items[--t->n_items];
     158   
     159    return ret;
    141160}
    142161
  • trunk/libtransmission/ptrarray.h

    r4404 r4876  
    2626void    tr_ptrArrayFree          ( tr_ptrArray*, PtrArrayForeachFunc func );
    2727void*   tr_ptrArrayNth           ( tr_ptrArray*, int n );
     28void*   tr_ptrArrayBack          ( tr_ptrArray* );
    2829void**  tr_ptrArrayPeek          ( tr_ptrArray*, int * size );
    2930void**  tr_ptrArrayBase          ( tr_ptrArray* );
     
    3132int     tr_ptrArrayInsert        ( tr_ptrArray*, void*, int pos );
    3233int     tr_ptrArrayAppend        ( tr_ptrArray*, void* );
     34void*   tr_ptrArrayPop           ( tr_ptrArray* );
    3335void    tr_ptrArrayErase         ( tr_ptrArray*, int begin, int end );
    3436int     tr_ptrArraySize          ( const tr_ptrArray* );
Note: See TracChangeset for help on using the changeset viewer.