static int testStackSmash( int depth ) { int i; int len; int err; uint8_t * in; const uint8_t * end; tr_benc val; char * saved; in = tr_new( uint8_t, depth * 2 + 1 ); for( i = 0; i < depth; ++i ) { in[i] = 'l'; in[depth + i] = 'e'; } in[depth * 2] = '\0'; err = tr_bencParse( in, in + ( depth * 2 ), &val, &end ); check( !err ); check( end == in + ( depth * 2 ) ); saved = tr_bencSave( &val, &len ); check( !strcmp( saved, (char*)in ) ); tr_free( in ); tr_free( saved ); tr_bencFree( &val ); return 0; }
static int testString( const char * str, int isGood ) { tr_benc 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 ); #if 0 fprintf( stderr, "in: [%s]\n", str ); fprintf( stderr, "out:\n%s", tr_bencSaveAsJSON( &val, NULL ) ); #endif 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; }
int tr_bencSave( benc_val_t * val, char ** buf, size_t * used, size_t * max ) { int ii; switch( val->type ) { case TYPE_INT: if( tr_bencSprintf( buf, used, max, "i%"PRIu64"e", val->val.i ) ) { return 1; } break; case TYPE_STR: if( (int)strlen(val->val.s.s) != val->val.s.i ) { return 1; } if( tr_bencSprintf( buf, used, max, "%i:%s", val->val.s.i, val->val.s.s ) ) { return 1; } break; case TYPE_LIST: case TYPE_DICT: if( tr_bencSprintf( buf, used, max, (TYPE_LIST == val->type ? "l" : "d") ) ) { return 1; } for( ii = 0; val->val.l.count > ii; ii++ ) { if( tr_bencSave( val->val.l.vals + ii, buf, used, max ) ) { return 1; } } if( tr_bencSprintf( buf, used, max, "e" ) ) { return 1; } break; } return 0; }
char * tr_bencSaveMalloc( benc_val_t * val, size_t * len ) { char * buf = NULL; size_t alloc = 0; *len = 0; if( tr_bencSave( val, &buf, len, &alloc ) ) { if( NULL != buf ) { free(buf); } *len = 0; return NULL; } return buf; }
static int testParse( void ) { tr_benc val; tr_benc * child; tr_benc * child2; uint8_t buf[512]; const uint8_t * end; int err; int len; int64_t i; char * saved; tr_snprintf( (char*)buf, sizeof( buf ), "i64e" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( tr_bencGetInt( &val, &i ) ); check( i == 64 ); check( end == buf + 4 ); tr_bencFree( &val ); tr_snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + strlen( (char*)buf ) ); check( val.val.l.count == 3 ); check( tr_bencGetInt( &val.val.l.vals[0], &i ) ); check( i == 64 ); check( tr_bencGetInt( &val.val.l.vals[1], &i ) ); check( i == 32 ); check( tr_bencGetInt( &val.val.l.vals[2], &i ) ); check( i == 16 ); saved = tr_bencSave( &val, &len ); check( !strcmp( saved, (char*)buf ) ); tr_free( saved ); tr_bencFree( &val ); end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "lllee" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); check( end == NULL ); end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "le" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + 2 ); saved = tr_bencSave( &val, &len ); check( !strcmp( saved, "le" ) ); 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( ( err = testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", TRUE ) ) ) return err; if( ( err = testString( "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", TRUE ) ) ) return err; 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; if( ( err = testString( " ", FALSE ) ) ) return err; /* nested containers * parse an unsorted dict * save as a sorted dict */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + strlen( (const char*)buf ) ); check( ( child = tr_bencListChild( &val, 0 ) ) ); check( ( child2 = tr_bencListChild( child, 0 ) ) ); saved = tr_bencSave( &val, &len ); check( !strcmp( saved, "lld1:ai64e1:bi32eeee" ) ); tr_free( saved ); tr_bencFree( &val ); /* too many endings */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "leee" ); err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end ); check( !err ); check( end == buf + 2 ); saved = tr_bencSave( &val, &len ); check( !strcmp( saved, "le" ) ); tr_free( saved ); tr_bencFree( &val ); /* no ending */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); /* incomplete string */ end = NULL; tr_snprintf( (char*)buf, sizeof( buf ), "1:" ); err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end ); check( err ); return 0; }