fix the 1.04 bencode errors reported in the forums this morning. add regression tests.

This commit is contained in:
Charles Kerr 2008-02-01 15:50:17 +00:00
parent 7394a49a09
commit 3334ea8401
2 changed files with 67 additions and 37 deletions

View File

@ -136,6 +136,29 @@ testStr( void )
return 0;
}
static int
testString( const char * str, int isGood )
{
benc_val_t val;
const uint8_t * end = NULL;
char * saved;
const size_t len = strlen( str );
int savedLen;
int err = tr_bencParse( str, str+len, &val , &end );
if( !isGood ) {
check( err );
} else {
check( !err );
check( end == (const uint8_t*)str + len );
saved = tr_bencSave( &val, &savedLen );
check( !strcmp( saved, str ) );
check( len == (size_t)savedLen );
tr_free( saved );
tr_bencFree( &val );
}
return 0;
}
static int
testParse( void )
{
@ -184,15 +207,22 @@ testParse( void )
tr_free( saved );
tr_bencFree( &val );
end = NULL;
snprintf( (char*)buf, sizeof( buf ), "llleee" );
err = tr_bencParse( buf, buf + sizeof( buf ), &val , &end );
check( !err );
check( end == buf + 6 );
saved = tr_bencSave( &val, &len );
check( !strcmp( saved, "llleee" ) );
tr_free( saved );
tr_bencFree( &val );
if(( err = testString( "llleee", TRUE )))
return err;
if(( err = testString( "d3:cow3:moo4:spam4:eggse", TRUE )))
return err;
if(( err = testString( "d4:spaml1:a1:bee", TRUE )))
return err;
#if 0
if(( err = testString( "d9:publisher3:bob18:publisher.location4:home17:publisher-webpage15:www.example.come", TRUE )))
return err;
#endif
if(( err = testString( "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", TRUE )))
return err;
if(( err = testString( "d1:ai0e1:be", FALSE ))) /* odd number of children */
return err;
if(( err = testString( "", FALSE )))
return err;
/* nested containers
* parse an unsorted dict
@ -209,13 +239,6 @@ testParse( void )
tr_free( saved );
tr_bencFree( &val );
end = NULL;
snprintf( (char*)buf, sizeof( buf ), "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e" );
err = tr_bencParse( buf, buf+sizeof( buf ), &val, &end );
check( !err );
check( end == buf + strlen( (const char*)buf ) );
tr_bencFree( &val );
return 0;
}

View File

@ -41,27 +41,25 @@
**/
static int
isInt( const benc_val_t * val )
isType( const benc_val_t * val, int type )
{
return val!=NULL && val->type==TYPE_INT;
return ( ( val != NULL ) && ( val->type == type ) );
}
static int
isList( const benc_val_t * val )
{
return val!=NULL && val->type==TYPE_LIST;
}
static int
isDict( const benc_val_t * val )
{
return val!=NULL && val->type==TYPE_DICT;
}
#define isInt(v) ( isType( ( v ), TYPE_INT ) )
#define isString(v) ( isType( ( v ), TYPE_STR ) )
#define isList(v) ( isType( ( v ), TYPE_LIST ) )
#define isDict(v) ( isType( ( v ), TYPE_DICT ) )
static int
isContainer( const benc_val_t * val )
{
return val!=NULL && ( val->type & ( TYPE_DICT | TYPE_LIST ) );
return isList(val) || isDict(val);
}
static int
isSomething( const benc_val_t * val )
{
return isContainer(val) || isInt(val) || isString(val);
}
benc_val_t*
@ -229,6 +227,8 @@ tr_bencParse( const void * buf_in,
const uint8_t * bufend = bufend_in;
tr_ptrArray * parentStack = tr_ptrArrayNew( );
tr_bencInit( top, 0 );
while( buf != bufend )
{
if( buf > bufend ) /* no more text to parse... */
@ -274,9 +274,15 @@ tr_bencParse( const void * buf_in,
}
else if( *buf=='e' ) /* end of list or dict */
{
benc_val_t * node;
++buf;
if( tr_ptrArrayEmpty( parentStack ) )
return TR_ERROR;
node = tr_ptrArrayBack( parentStack );
if( isDict( node ) && ( node->val.l.count % 2 ) )
return TR_ERROR; /* odd # of children in dict */
tr_ptrArrayPop( parentStack );
if( tr_ptrArrayEmpty( parentStack ) )
break;
@ -308,7 +314,7 @@ tr_bencParse( const void * buf_in,
}
}
err = tr_ptrArrayEmpty( parentStack ) ? 0 : 1;
err = !isSomething( top ) || !tr_ptrArrayEmpty( parentStack );
if( !err && ( setme_end != NULL ) )
*setme_end = buf;
@ -511,20 +517,21 @@ struct SaveNode
static struct SaveNode*
nodeNewDict( const benc_val_t * val )
{
int i, j, n;
int i, j;
int nKeys;
struct SaveNode * node;
struct KeyIndex * indices;
assert( isDict( val ) );
n = val->val.l.count;
nKeys = val->val.l.count / 2;
node = tr_new0( struct SaveNode, 1 );
node->val = val;
node->children = tr_new0( int, n );
node->children = tr_new0( int, nKeys * 2 );
/* ugh, a dictionary's children have to be sorted by key... */
indices = tr_new( struct KeyIndex, n );
for( i=j=0; i<n; i+=2, ++j ) {
indices = tr_new( struct KeyIndex, nKeys );
for( i=j=0; i<(nKeys*2); i+=2, ++j ) {
indices[j].key = val->val.l.vals[i].val.s.s;
indices[j].index = i;
}
@ -535,7 +542,7 @@ nodeNewDict( const benc_val_t * val )
node->children[ node->childCount++ ] = index + 1;
}
assert( node->childCount == n );
assert( node->childCount == nKeys * 2 );
tr_free( indices );
return node;
}