Changeset 4892


Ignore:
Timestamp:
Feb 1, 2008, 3:50:12 PM (14 years ago)
Author:
charles
Message:

(1.0x) fix the 1.04 bencode errors reported in the forums this morning. add regression tests.

Location:
branches/1.0x/libtransmission
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/1.0x/libtransmission/bencode-test.c

    r4883 r4892  
    2525    uint8_t buf[128];
    2626    int64_t val;
    27     unsigned int err;
     27    int err;
    2828    const uint8_t * end;
    2929
     
    3939    val = 888;
    4040    err = tr_bencParseInt( buf, buf+3, &end, &val );
    41     check( err == TR_ERROR );
     41    check( err == (int)TR_ERROR );
    4242    check( val == 888 );
    4343    check( end == NULL );
     
    4545    /* empty buffer */
    4646    err = tr_bencParseInt( buf, buf+0, &end, &val );
    47     check( err == TR_ERROR );
     47    check( err == (int)TR_ERROR );
    4848    check( val == 888 );
    4949    check( end == NULL );
     
    5252    snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
    5353    err = tr_bencParseInt( buf, buf+5, &end, &val );
    54     check( err == TR_ERROR );
     54    check( err == (int)TR_ERROR );
    5555    check( val == 888 );
    5656    check( end == NULL );
     
    7575    snprintf( (char*)buf, sizeof( buf ), "i04e" );
    7676    err = tr_bencParseInt( buf, buf+4, &end, &val );
    77     check( err == TR_ERROR );
     77    check( err == (int)TR_ERROR );
    7878    check( val == 0 );
    7979    check( end == NULL );
     
    8686{
    8787    uint8_t buf[128];
    88     unsigned int err;
     88    int err;
    8989    const uint8_t * end;
    9090    uint8_t * str;
     
    105105    /* string goes past end of buffer */
    106106    err = tr_bencParseStr( buf, buf+5, &end, &str, &len );
    107     check( err == TR_ERROR );
     107    check( err == (int)TR_ERROR );
    108108    check( str == NULL );
    109109    check( end == NULL );
     
    138138
    139139static int
     140testString( const char * str, int isGood )
     141{
     142    benc_val_t val;
     143    const uint8_t * end = NULL;
     144    char * saved;
     145    const size_t len = strlen( str );
     146    int savedLen;
     147    int err = tr_bencParse( str, str+len, &val , &end );
     148    if( !isGood ) {
     149        check( err );
     150    } else {
     151        check( !err );
     152        check( end == (const uint8_t*)str + len );
     153        saved = tr_bencSave( &val, &savedLen );
     154        check( !strcmp( saved, str ) );
     155        check( len == (size_t)savedLen );
     156        tr_free( saved );
     157        tr_bencFree( &val );
     158    }
     159    return 0;
     160}
     161
     162static int
    140163testParse( void )
    141164{
     
    185208    tr_bencFree( &val );
    186209
    187     end = NULL;
    188     snprintf( (char*)buf, sizeof( buf ), "llleee" );
    189     err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
    190     check( !err );
    191     check( end == buf + 6 );
    192     saved = tr_bencSave( &val, &len );
    193     check( !strcmp( saved, "llleee" ) );
    194     tr_free( saved );
    195     tr_bencFree( &val );
     210    if(( err = testString( "llleee", TRUE )))
     211        return err;
     212    if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
     213        return err;
     214    if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
     215        return err;
     216#if 0
     217    if(( err = testString( "d9:publisher3:bob18:publisher.location4:home17:publisher-webpage15:www.example.come", TRUE )))
     218        return err;
     219#endif
     220    if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
     221        return err;
     222    if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
     223        return err;
     224    if(( err = testString( "", FALSE )))
     225        return err;
    196226
    197227    /* nested containers
     
    208238    check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) );
    209239    tr_free( saved );
    210     tr_bencFree( &val );
    211 
    212     end = NULL;
    213     snprintf( (char*)buf, sizeof( buf ), "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e" );
    214     err = tr_bencParse( buf, buf+sizeof( buf ), &val, &end );
    215     check( !err );
    216     check( end == buf + strlen( (const char*)buf ) );
    217240    tr_bencFree( &val );
    218241
  • branches/1.0x/libtransmission/bencode.c

    r4883 r4892  
    3030#include <stdlib.h>
    3131
    32 #include <event.h>
     32#include <event.h> /* evbuffer */
    3333
    3434#include "transmission.h"
    3535#include "bencode.h"
    3636#include "ptrarray.h"
    37 #include "utils.h"
     37#include "utils.h" /* tr_new(), tr_free() */
    3838
    3939/**
     
    4242
    4343static int
    44 tr_bencIsInt( const benc_val_t * val )
    45 {
    46     return val!=NULL && val->type==TYPE_INT;
    47 }
    48 
    49 static int
    50 tr_bencIsList( const benc_val_t * val )
    51 {
    52     return val!=NULL && val->type==TYPE_LIST;
    53 }
    54 
    55 static int
    56 tr_bencIsDict( const benc_val_t * val )
    57 {
    58     return val!=NULL && val->type==TYPE_DICT;
    59 }
     44isType( const benc_val_t * val, int type )
     45{
     46    return ( ( val != NULL ) && ( val->type == type ) );
     47}
     48
     49#define isInt(v)    ( isType( ( v ), TYPE_INT ) )
     50#define isString(v) ( isType( ( v ), TYPE_STR ) )
     51#define isList(v)   ( isType( ( v ), TYPE_LIST ) )
     52#define isDict(v)   ( isType( ( v ), TYPE_DICT ) )
    6053
    6154static int
    6255isContainer( const benc_val_t * val )
    6356{
    64     return val!=NULL && ( val->type & ( TYPE_DICT | TYPE_LIST ) );
     57    return isList(val) || isDict(val);
     58}
     59static int
     60isSomething( const benc_val_t * val )
     61{
     62    return isContainer(val) || isInt(val) || isString(val);
    6563}
    6664
     
    6967{
    7068    benc_val_t * ret = NULL;
    71     if( tr_bencIsList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
     69    if( isList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
    7270        ret = val->val.l.vals + i;
    7371    return ret;
     
    215213
    216214/**
    217  * this function's awkward stack-based implementation
    218  * is to prevent maliciously-crafed bencode data from
    219  * smashing our stack through deep recursion. (#667)
     215 * This function's previous recursive implementation was
     216 * easier to read, but was vulnerable to a smash-stacking
     217 * attack via maliciously-crafted bencoded data. (#667)
    220218 */
    221219int
     
    230228    tr_ptrArray * parentStack = tr_ptrArrayNew( );
    231229
     230    tr_bencInit( top, 0 );
     231
    232232    while( buf != bufend )
    233233    {
     
    275275        else if( *buf=='e' ) /* end of list or dict */
    276276        {
     277            benc_val_t * node;
    277278            ++buf;
    278279            if( tr_ptrArrayEmpty( parentStack ) )
    279280                return TR_ERROR;
     281
     282            node = tr_ptrArrayBack( parentStack );
     283            if( isDict( node ) && ( node->val.l.count % 2 ) )
     284                return TR_ERROR; /* odd # of children in dict */
     285
    280286            tr_ptrArrayPop( parentStack );
    281287            if( tr_ptrArrayEmpty( parentStack ) )
     
    309315    }
    310316
    311     err = tr_ptrArrayEmpty( parentStack ) ? 0 : 1;
     317    err = !isSomething( top ) || !tr_ptrArrayEmpty( parentStack );
    312318
    313319    if( !err && ( setme_end != NULL ) )
     
    368374tr_bencGetInt ( const benc_val_t * val )
    369375{
    370     assert( tr_bencIsInt( val ) );
     376    assert( isInt( val ) );
    371377    return val->val.i;
    372378}
     
    454460    benc_val_t * item;
    455461
    456     assert( tr_bencIsList( list ) );
     462    assert( isList( list ) );
    457463    assert( list->val.l.count < list->val.l.alloc );
    458464
     
    469475    benc_val_t * keyval, * itemval;
    470476
    471     assert( tr_bencIsDict( dict ) );
     477    assert( isDict( dict ) );
    472478    assert( dict->val.l.count + 2 <= dict->val.l.alloc );
    473479
     
    503509{
    504510    const benc_val_t * val;
    505     int valIsSaved;
     511    int valIsVisited;
    506512    int childCount;
    507513    int childIndex;
     
    512518nodeNewDict( const benc_val_t * val )
    513519{
    514     int i, j, n;
     520    int i, j;
     521    int nKeys;
    515522    struct SaveNode * node;
    516523    struct KeyIndex * indices;
    517524
    518     assert( tr_bencIsDict( val ) );
    519 
    520     n = val->val.l.count;
     525    assert( isDict( val ) );
     526
     527    nKeys = val->val.l.count / 2;
    521528    node = tr_new0( struct SaveNode, 1 );
    522529    node->val = val;
    523     node->children = tr_new0( int, n );
     530    node->children = tr_new0( int, nKeys * 2 );
    524531
    525532    /* ugh, a dictionary's children have to be sorted by key... */
    526     indices = tr_new( struct KeyIndex, n );
    527     for( i=j=0; i<n; i+=2, ++j ) {
     533    indices = tr_new( struct KeyIndex, nKeys );
     534    for( i=j=0; i<(nKeys*2); i+=2, ++j ) {
    528535        indices[j].key = val->val.l.vals[i].val.s.s;
    529536        indices[j].index = i;
     
    536543    }
    537544
    538     assert( node->childCount == n );
     545    assert( node->childCount == nKeys * 2 );
    539546    tr_free( indices );
    540547    return node;
     
    547554    struct SaveNode * node;
    548555
    549     assert( tr_bencIsList( val ) );
     556    assert( isList( val ) );
    550557
    551558    n = val->val.l.count;
     
    599606
    600607/**
    601  * this function's awkward stack-based implementation
    602  * is to prevent maliciously-crafed bencode data from
    603  * smashing our stack through deep recursion. (#667)
     608 * This function's previous recursive implementation was
     609 * easier to read, but was vulnerable to a smash-stacking
     610 * attack via maliciously-crafted bencoded data. (#667)
    604611 */
    605612static void
     
    616623        const benc_val_t * val;
    617624
    618         if( !node->valIsSaved )
     625        if( !node->valIsVisited )
    619626        {
    620627            val = node->val;
    621             node->valIsSaved = TRUE;
     628            node->valIsVisited = TRUE;
    622629        }
    623630        else if( node->childIndex < node->childCount )
Note: See TracChangeset for help on using the changeset viewer.