Changeset 4876
- Timestamp:
- Jan 31, 2008, 2:24:43 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/daemon/torrents.c
r4306 r4876 612 612 timerfunc( int fd UNUSED, short event UNUSED, void * arg UNUSED ) 613 613 { 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; 618 618 619 619 /* true if we've still got live torrents... */ -
trunk/gtk/ipc.c
r4739 r4876 978 978 smsg_pref( enum ipc_msg id, benc_val_t * val UNUSED, int64_t tag, void * arg ) 979 979 { 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; 987 987 988 988 switch( id ) -
trunk/libtransmission/bencode-test.c
r4869 r4876 4 4 #include "utils.h" /* tr_free */ 5 5 6 #define VERBOSE 16 #define VERBOSE 0 7 7 8 8 int test = 0; … … 30 30 /* good int string */ 31 31 snprintf( (char*)buf, sizeof( buf ), "i64e" ); 32 err = tr_bencParseInt( buf, 4, &end, &val );32 err = tr_bencParseInt( buf, buf+4, &end, &val ); 33 33 check( err == 0 ); 34 34 check( val == 64 ); … … 38 38 end = NULL; 39 39 val = 888; 40 err = tr_bencParseInt( buf, 3, &end, &val );40 err = tr_bencParseInt( buf, buf+3, &end, &val ); 41 41 check( err == TR_ERROR ); 42 42 check( val == 888 ); … … 44 44 45 45 /* empty buffer */ 46 err = tr_bencParseInt( buf, 0, &end, &val );46 err = tr_bencParseInt( buf, buf+0, &end, &val ); 47 47 check( err == TR_ERROR ); 48 48 check( val == 888 ); … … 51 51 /* bad number */ 52 52 snprintf( (char*)buf, sizeof( buf ), "i6z4e" ); 53 err = tr_bencParseInt( buf, 4, &end, &val );53 err = tr_bencParseInt( buf, buf+5, &end, &val ); 54 54 check( err == TR_ERROR ); 55 55 check( val == 888 ); … … 58 58 /* negative number */ 59 59 snprintf( (char*)buf, sizeof( buf ), "i-3e" ); 60 err = tr_bencParseInt( buf, 4, &end, &val );60 err = tr_bencParseInt( buf, buf+4, &end, &val ); 61 61 check( err == TR_OK ); 62 62 check( val == -3 ); … … 65 65 /* zero */ 66 66 snprintf( (char*)buf, sizeof( buf ), "i0e" ); 67 err = tr_bencParseInt( buf, 4, &end, &val );67 err = tr_bencParseInt( buf, buf+4, &end, &val ); 68 68 check( err == TR_OK ); 69 69 check( val == 0 ); … … 74 74 end = NULL; 75 75 snprintf( (char*)buf, sizeof( buf ), "i04e" ); 76 err = tr_bencParseInt( buf, 4, &end, &val );76 err = tr_bencParseInt( buf, buf+4, &end, &val ); 77 77 check( err == TR_ERROR ); 78 78 check( val == 0 ); … … 93 93 /* good string */ 94 94 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 ); 96 96 check( err == TR_OK ); 97 97 check( !strcmp( (char*)str, "boat" ) ); … … 104 104 105 105 /* 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 ); 107 107 check( err == TR_ERROR ); 108 108 check( str == NULL ); … … 112 112 /* empty string */ 113 113 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 ); 115 115 check( err == TR_OK ); 116 116 check( !*str ); … … 124 124 /* short string */ 125 125 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 ); 127 127 check( err == TR_OK ); 128 128 check( !strcmp( (char*)str, "boa" ) ); … … 136 136 return 0; 137 137 } 138 138 139 static int 140 testParse( 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 220 static int 221 testStackSmash( 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 139 253 int 140 254 main( void ) … … 142 256 int i; 143 257 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 34 34 #include "transmission.h" 35 35 #include "bencode.h" 36 #include "ptrarray.h" 36 37 #include "utils.h" 37 38 … … 40 41 **/ 41 42 43 int 44 tr_bencIsInt( const benc_val_t * val ) 45 { 46 return val!=NULL && val->type==TYPE_INT; 47 } 48 49 int 50 tr_bencIsString( const benc_val_t * val ) 51 { 52 return val!=NULL && val->type==TYPE_STR; 53 } 54 55 int 56 tr_bencIsList( const benc_val_t * val ) 57 { 58 return val!=NULL && val->type==TYPE_LIST; 59 } 60 61 int 62 tr_bencIsDict( const benc_val_t * val ) 63 { 64 return val!=NULL && val->type==TYPE_DICT; 65 } 66 42 67 static 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 } 68 isContainer( const benc_val_t * val ) 69 { 70 return val!=NULL && ( val->type & ( TYPE_DICT | TYPE_LIST ) ); 71 } 72 73 benc_val_t* 74 tr_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 56 82 57 83 /** … … 70 96 int 71 97 tr_bencParseInt( const uint8_t * buf, 72 size_t buflen,98 const uint8_t * bufend, 73 99 const uint8_t ** setme_end, 74 100 int64_t * setme_val ) … … 80 106 int64_t val; 81 107 82 if( !buflen)108 if( buf >= bufend ) 83 109 return TR_ERROR; 84 110 if( *buf != 'i' ) … … 86 112 87 113 begin = buf + 1; 88 end = memchr( begin, 'e', buflen-1 );114 end = memchr( begin, 'e', (bufend-buf)-1 ); 89 115 if( end == NULL ) 90 116 return TR_ERROR; … … 113 139 int 114 140 tr_bencParseStr( const uint8_t * buf, 115 size_t buflen,141 const uint8_t * bufend, 116 142 const uint8_t ** setme_end, 117 143 uint8_t ** setme_str, … … 122 148 char * endptr; 123 149 124 if( !buflen)150 if( buf >= bufend ) 125 151 return TR_ERROR; 126 152 … … 128 154 return TR_ERROR; 129 155 130 end = memchr( buf, ':', buf len);156 end = memchr( buf, ':', bufend-buf ); 131 157 if( end == NULL ) 132 158 return TR_ERROR; … … 137 163 return TR_ERROR; 138 164 139 if( ( (const uint8_t*)end - buf ) + 1 + len > buflen)165 if( (const uint8_t*)end + 1 + len > bufend ) 140 166 return TR_ERROR; 141 167 … … 147 173 148 174 /* 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 177 static int 178 makeroom( benc_val_t * val, int count ) 152 179 { 153 180 assert( TYPE_LIST == val->type || TYPE_DICT == val->type ); … … 169 196 } 170 197 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... */ 198 static benc_val_t* 199 getNode( 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 */ 227 int 228 tr_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... */ 184 241 return 1; 185 242 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; 282 310 } 283 311 else /* invalid bencoded text... march past it */ 284 312 { 285 313 ++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 326 int 327 tr_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 340 benc_val_t * 341 tr_bencDictFind( benc_val_t * val, const char * key ) 379 342 { 380 343 int len, ii; … … 401 364 } 402 365 403 benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... ) 366 benc_val_t* 367 tr_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 373 int64_t 374 tr_bencGetInt ( const benc_val_t * val ) 375 { 376 assert( tr_bencIsInt( val ) ); 377 return val->val.i; 378 } 379 380 benc_val_t * 381 tr_bencDictFindFirst( benc_val_t * val, ... ) 404 382 { 405 383 const char * key; … … 422 400 } 423 401 424 char * tr_bencStealStr( benc_val_t * val ) 402 char * 403 tr_bencStealStr( benc_val_t * val ) 425 404 { 426 405 assert( TYPE_STR == val->type ); … … 429 408 } 430 409 431 void _tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree ) 410 void 411 _tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree ) 432 412 { 433 413 tr_bencInit( val, TYPE_STR ); … … 441 421 } 442 422 443 int tr_bencInitStrDup( benc_val_t * val, const char * str ) 423 int 424 tr_bencInitStrDup( benc_val_t * val, const char * str ) 444 425 { 445 426 char * newStr = tr_strdup( str ); … … 451 432 } 452 433 453 void tr_bencInitInt( benc_val_t * val, int64_t num ) 434 void 435 tr_bencInitInt( benc_val_t * val, int64_t num ) 454 436 { 455 437 tr_bencInit( val, TYPE_INT ); … … 457 439 } 458 440 459 int tr_bencListReserve( benc_val_t * val, int count ) 441 int 442 tr_bencListReserve( benc_val_t * val, int count ) 460 443 { 461 444 assert( TYPE_LIST == val->type ); … … 464 447 } 465 448 466 int tr_bencDictReserve( benc_val_t * val, int count ) 449 int 450 tr_bencDictReserve( benc_val_t * val, int count ) 467 451 { 468 452 assert( TYPE_DICT == val->type ); … … 471 455 } 472 456 473 benc_val_t * tr_bencListAdd( benc_val_t * list ) 457 benc_val_t * 458 tr_bencListAdd( benc_val_t * list ) 474 459 { 475 460 benc_val_t * item; … … 485 470 } 486 471 487 benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key ) 472 benc_val_t * 473 tr_bencDictAdd( benc_val_t * dict, const char * key ) 488 474 { 489 475 benc_val_t * keyval, * itemval; … … 500 486 return itemval; 501 487 } 488 489 490 /*** 491 **** BENC WALKING 492 ***/ 502 493 503 494 struct KeyIndex … … 507 498 }; 508 499 509 static int compareKeyIndex( const void * va, const void * vb ) 500 static int 501 compareKeyIndex( const void * va, const void * vb ) 510 502 { 511 503 const struct KeyIndex * a = va; … … 514 506 } 515 507 516 static void 517 saveImpl( struct evbuffer * out, const benc_val_t * val ) 508 struct SaveNode 509 { 510 const benc_val_t * val; 511 int valIsSaved; 512 int childCount; 513 int childIndex; 514 int * children; 515 }; 516 517 static struct SaveNode* 518 nodeNewDict( 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 549 static struct SaveNode* 550 nodeNewList( 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 568 static struct SaveNode* 569 nodeNewSimple( 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 580 static struct SaveNode* 581 nodeNew( 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 601 typedef void (*BencNodeWalkFunc)( const benc_val_t * val, void * user_data ); 602 603 struct 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 */ 617 static void 618 depthFirstWalk( 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 684 static void 685 saveIntFunc( const benc_val_t * val, void * buf ) 686 { 687 evbuffer_add_printf( buf, "i%"PRId64"e", tr_bencGetInt(val) ); 688 } 689 static void 690 saveStringFunc( 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 } 696 static void 697 saveDictBeginFunc( const benc_val_t * val UNUSED, void * buf ) 698 { 699 evbuffer_add_printf( buf, "d" ); 700 } 701 static void 702 saveListBeginFunc( const benc_val_t * val UNUSED, void * buf ) 703 { 704 evbuffer_add_printf( buf, "l" ); 705 } 706 static void 707 saveContainerEndFunc( const benc_val_t * val UNUSED, void * buf ) 708 { 709 evbuffer_add_printf( buf, "e" ); 710 } 711 char* 712 tr_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 737 static void 738 freeDummyFunc( const benc_val_t * val UNUSED, void * buf UNUSED ) 739 { 740 } 741 static void 742 freeStringFunc( const benc_val_t * val, void * freeme ) 743 { 744 if( !val->val.s.nofree ) 745 tr_ptrArrayAppend( freeme, val->val.s.s ); 746 } 747 static void 748 freeContainerBeginFunc( const benc_val_t * val, void * freeme ) 749 { 750 tr_ptrArrayAppend( freeme, val->val.l.vals ); 751 } 752 void 753 tr_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 775 struct WalkPrint 776 { 777 int depth; 778 FILE * out; 779 }; 780 static void 781 printLeadingSpaces( struct WalkPrint * data ) 782 { 783 const int width = data->depth * 2; 784 fprintf( data->out, "%*.*s", width, width, " " ); 785 } 786 static void 787 printIntFunc( 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 } 793 static void 794 printStringFunc( const benc_val_t * val, void * vdata ) 518 795 { 519 796 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 } 811 static void 812 printListBeginFunc( 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 } 819 static void 820 printDictBeginFunc( 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 } 827 static void 828 printContainerEndFunc( const benc_val_t * val UNUSED, void * vdata ) 829 { 830 struct WalkPrint * data = vdata; 831 --data->depth; 832 } 833 void 834 tr_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 47 47 struct 48 48 { 49 int 50 int 49 int alloc; 50 int count; 51 51 struct benc_val_s * vals; 52 52 } l; … … 55 55 56 56 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 ); 57 int tr_bencParse( const void * buf, 58 const void * bufend, 59 benc_val_t * setme_benc, 60 const uint8_t ** setme_end ); 61 62 int tr_bencLoad( const void * buf, 63 int buflen, 64 benc_val_t * setme_benc, 65 char ** setme_end ); 66 60 67 void tr_bencPrint( benc_val_t * val ); 61 68 void tr_bencFree( benc_val_t * val ); … … 98 105 99 106 int tr_bencParseInt( const uint8_t * buf, 100 size_t buflen,107 const uint8_t * bufend, 101 108 const uint8_t ** setme_end, 102 109 int64_t * setme_val ); 103 110 104 111 int tr_bencParseStr( const uint8_t * buf, 105 size_t buflen,112 const uint8_t * bufend, 106 113 const uint8_t ** setme_end, 107 114 uint8_t ** setme_str, 108 115 size_t * setme_strlen ); 109 116 117 /** 118 *** 119 **/ 120 121 int tr_bencIsInt( const benc_val_t * val ); 122 int tr_bencIsList( const benc_val_t * val ); 123 int tr_bencIsDict( const benc_val_t * val ); 124 int tr_bencIsString( const benc_val_t * val ); 125 126 benc_val_t* tr_bencListGetNthChild( benc_val_t * val, int i ); 127 128 110 129 111 130 -
trunk/libtransmission/ptrarray.c
r4404 r4876 97 97 } 98 98 99 void* 100 tr_ptrArrayBack( tr_ptrArray* t ) 101 { 102 assert( t->n_items > 0 ); 103 104 return tr_ptrArrayNth( t, t->n_items-1 ); 105 } 106 99 107 int 100 108 tr_ptrArraySize( const tr_ptrArray * t ) … … 139 147 { 140 148 return tr_ptrArrayInsert( t, ptr, -1 ); 149 } 150 151 void* 152 tr_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; 141 160 } 142 161 -
trunk/libtransmission/ptrarray.h
r4404 r4876 26 26 void tr_ptrArrayFree ( tr_ptrArray*, PtrArrayForeachFunc func ); 27 27 void* tr_ptrArrayNth ( tr_ptrArray*, int n ); 28 void* tr_ptrArrayBack ( tr_ptrArray* ); 28 29 void** tr_ptrArrayPeek ( tr_ptrArray*, int * size ); 29 30 void** tr_ptrArrayBase ( tr_ptrArray* ); … … 31 32 int tr_ptrArrayInsert ( tr_ptrArray*, void*, int pos ); 32 33 int tr_ptrArrayAppend ( tr_ptrArray*, void* ); 34 void* tr_ptrArrayPop ( tr_ptrArray* ); 33 35 void tr_ptrArrayErase ( tr_ptrArray*, int begin, int end ); 34 36 int tr_ptrArraySize ( const tr_ptrArray* );
Note: See TracChangeset
for help on using the changeset viewer.