• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/libtransmission/
1#include <ctype.h> /* isspace() */
2#include <errno.h> /* EILSEQ */
3#include <string.h> /* strlen(), strncmp() */
4
5#include <event2/buffer.h>
6
7#include "transmission.h"
8#include "bencode.h"
9#include "utils.h" /* tr_free */
10
11// #define VERBOSE
12#include "libtransmission-test.h"
13
14#ifndef WIN32
15#define STACK_SMASH_DEPTH (1 * 1000 * 1000)
16#else
17#define STACK_SMASH_DEPTH (     100 * 1000)
18#endif
19
20static int
21testInt( void )
22{
23    uint8_t         buf[128];
24    int64_t         val;
25    int             err;
26    const uint8_t * end;
27
28    /* good int string */
29    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
30    err = tr_bencParseInt( buf, buf + 4, &end, &val );
31    check_int_eq( 0, err );
32    check_int_eq( 64, val );
33    check( (buf + 4) ==  end );
34
35    /* missing 'e' */
36    end = NULL;
37    val = 888;
38    err = tr_bencParseInt( buf, buf + 3, &end, &val );
39    check_int_eq( EILSEQ, err );
40    check_int_eq( 888, val );
41    check( end == NULL );
42
43    /* empty buffer */
44    err = tr_bencParseInt( buf, buf + 0, &end, &val );
45    check_int_eq( EILSEQ, err );
46    check_int_eq( 888, val );
47    check( end == NULL );
48
49    /* bad number */
50    tr_snprintf( (char*)buf, sizeof( buf ), "i6z4e" );
51    err = tr_bencParseInt( buf, buf + 5, &end, &val );
52    check_int_eq( EILSEQ, err );
53    check_int_eq( 888, val );
54    check( end == NULL );
55
56    /* negative number */
57    tr_snprintf( (char*)buf, sizeof( buf ), "i-3e" );
58    err = tr_bencParseInt( buf, buf + 4, &end, &val );
59    check_int_eq( 0, err );
60    check_int_eq( -3, val );
61    check( (buf + 4) == end );
62
63    /* zero */
64    tr_snprintf( (char*)buf, sizeof( buf ), "i0e" );
65    err = tr_bencParseInt( buf, buf + 4, &end, &val );
66    check_int_eq( 0, err );
67    check_int_eq( 0, val );
68    check( (buf + 3) == end );
69
70    /* no leading zeroes allowed */
71    val = 0;
72    end = NULL;
73    tr_snprintf( (char*)buf, sizeof( buf ), "i04e" );
74    err = tr_bencParseInt( buf, buf + 4, &end, &val );
75    check_int_eq( EILSEQ, err );
76    check_int_eq( 0, val );
77    check( NULL == end );
78
79    return 0;
80}
81
82static int
83testStr( void )
84{
85    uint8_t         buf[128];
86    int             err;
87    const uint8_t * end;
88    const uint8_t * str;
89    size_t          len;
90
91    /* good string */
92    tr_snprintf( (char*)buf, sizeof( buf ), "4:boat" );
93    err = tr_bencParseStr( buf, buf + 6, &end, &str, &len );
94    check_int_eq (0, err);
95    check_int_eq (4, len);
96    check( !strncmp( (char*)str, "boat", len ) );
97    check( end == buf + 6 );
98    str = NULL;
99    end = NULL;
100    len = 0;
101
102    /* string goes past end of buffer */
103    err = tr_bencParseStr( buf, buf + 5, &end, &str, &len );
104    check_int_eq (EILSEQ, err);
105    check_int_eq (0, len);
106    check( str == NULL );
107    check( end == NULL );
108    check( !len );
109
110    /* empty string */
111    tr_snprintf( (char*)buf, sizeof( buf ), "0:" );
112    err = tr_bencParseStr( buf, buf + 2, &end, &str, &len );
113    check_int_eq (0, err);
114    check_int_eq (0, len);
115    check( !*str );
116    check( end == buf + 2 );
117    str = NULL;
118    end = NULL;
119    len = 0;
120
121    /* short string */
122    tr_snprintf( (char*)buf, sizeof( buf ), "3:boat" );
123    err = tr_bencParseStr( buf, buf + 6, &end, &str, &len );
124    check_int_eq (0, err);
125    check_int_eq (3, len);
126    check( !strncmp( (char*)str, "boa", len ) );
127    check( end == buf + 5 );
128    str = NULL;
129    end = NULL;
130    len = 0;
131
132    return 0;
133}
134
135static int
136testString( const char * str,
137            int          isGood )
138{
139    tr_benc         val;
140    const uint8_t * end = NULL;
141    char *          saved;
142    const size_t    len = strlen( str );
143    int             savedLen;
144    int             err = tr_bencParse( str, str + len, &val, &end );
145
146    if( !isGood )
147    {
148        check( err );
149    }
150    else
151    {
152        check( !err );
153#if 0
154        fprintf( stderr, "in: [%s]\n", str );
155        fprintf( stderr, "out:\n%s", tr_bencToStr( &val, TR_FMT_JSON, NULL ) );
156#endif
157        check( end == (const uint8_t*)str + len );
158        saved = tr_bencToStr( &val, TR_FMT_BENC, &savedLen );
159        check_streq (str, saved);
160        check_int_eq (savedLen, len);
161        tr_free( saved );
162        tr_bencFree( &val );
163    }
164    return 0;
165}
166
167static int
168testParse( void )
169{
170    tr_benc         val;
171    tr_benc *       child;
172    tr_benc *       child2;
173    uint8_t         buf[512];
174    const uint8_t * end;
175    int             err;
176    int             len;
177    int64_t         i;
178    char *          saved;
179
180    tr_snprintf( (char*)buf, sizeof( buf ), "i64e" );
181    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
182    check( !err );
183    check( tr_bencGetInt( &val, &i ) );
184    check_int_eq (64, i);
185    check( end == buf + 4 );
186    tr_bencFree( &val );
187
188    tr_snprintf( (char*)buf, sizeof( buf ), "li64ei32ei16ee" );
189    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
190    check( !err );
191    check( end == buf + strlen( (char*)buf ) );
192    check( val.val.l.count == 3 );
193    check( tr_bencGetInt( &val.val.l.vals[0], &i ) );
194    check_int_eq (64, i);
195    check( tr_bencGetInt( &val.val.l.vals[1], &i ) );
196    check_int_eq (32, i);
197    check( tr_bencGetInt( &val.val.l.vals[2], &i ) );
198    check_int_eq (16, i);
199    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
200    check_streq ((char*)buf, saved);
201    tr_free( saved );
202    tr_bencFree( &val );
203
204    end = NULL;
205    tr_snprintf( (char*)buf, sizeof( buf ), "lllee" );
206    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
207    check( err );
208    check( end == NULL );
209
210    end = NULL;
211    tr_snprintf( (char*)buf, sizeof( buf ), "le" );
212    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
213    check( !err );
214    check( end == buf + 2 );
215    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
216    check_streq( "le", saved );
217    tr_free( saved );
218    tr_bencFree( &val );
219
220    if( ( err = testString( "llleee", true ) ) )
221        return err;
222    if( ( err = testString( "d3:cow3:moo4:spam4:eggse", true ) ) )
223        return err;
224    if( ( err = testString( "d4:spaml1:a1:bee", true ) ) )
225        return err;
226    if( ( err =
227             testString( "d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee",
228                         true ) ) )
229        return err;
230    if( ( err =
231             testString(
232                 "d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee",
233                 true ) ) )
234        return err;
235    if( ( err =
236             testString(
237                 "d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e",
238                 true ) ) )
239        return err;
240    if( ( err = testString( "d1:ai0e1:be", false ) ) ) /* odd number of children
241                                                         */
242        return err;
243    if( ( err = testString( "", false ) ) )
244        return err;
245    if( ( err = testString( " ", false ) ) )
246        return err;
247
248    /* nested containers
249     * parse an unsorted dict
250     * save as a sorted dict */
251    end = NULL;
252    tr_snprintf( (char*)buf, sizeof( buf ), "lld1:bi32e1:ai64eeee" );
253    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
254    check( !err );
255    check( end == buf + strlen( (const char*)buf ) );
256    check( ( child = tr_bencListChild( &val, 0 ) ) );
257    check( ( child2 = tr_bencListChild( child, 0 ) ) );
258    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
259    check_streq( "lld1:ai64e1:bi32eeee", saved );
260    tr_free( saved );
261    tr_bencFree( &val );
262
263    /* too many endings */
264    end = NULL;
265    tr_snprintf( (char*)buf, sizeof( buf ), "leee" );
266    err = tr_bencParse( buf, buf + sizeof( buf ), &val, &end );
267    check( !err );
268    check( end == buf + 2 );
269    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
270    check_streq( "le", saved );
271    tr_free( saved );
272    tr_bencFree( &val );
273
274    /* no ending */
275    end = NULL;
276    tr_snprintf( (char*)buf, sizeof( buf ), "l1:a1:b1:c" );
277    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
278    check( err );
279
280    /* incomplete string */
281    end = NULL;
282    tr_snprintf( (char*)buf, sizeof( buf ), "1:" );
283    err = tr_bencParse( buf, buf + strlen( (char*)buf ), &val, &end );
284    check( err );
285
286    return 0;
287}
288
289static void
290stripWhitespace( char * in )
291{
292    char * out;
293
294    for( out = in; *in; ++in )
295        if( !isspace( *in ) )
296            *out++ = *in;
297    *out = '\0';
298}
299
300static int
301testJSONSnippet( const char * benc_str,
302                 const char * expected )
303{
304    tr_benc top;
305    char * serialized;
306    struct evbuffer * buf;
307
308    tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL );
309    buf = tr_bencToBuf( &top, TR_FMT_JSON );
310    serialized = (char*) evbuffer_pullup( buf, -1 );
311    stripWhitespace( serialized );
312#if 0
313    fprintf( stderr, "benc: %s\n", benc_str );
314    fprintf( stderr, "json: %s\n", serialized );
315    fprintf( stderr, "want: %s\n", expected );
316#endif
317    check_streq (expected, serialized);
318    tr_bencFree( &top );
319    evbuffer_free( buf );
320    return 0;
321}
322
323static int
324testJSON( void )
325{
326    int          val;
327    const char * benc_str;
328    const char * expected;
329
330    benc_str = "i6e";
331    expected = "6";
332    if( ( val = testJSONSnippet( benc_str, expected ) ) )
333        return val;
334
335    benc_str = "d5:helloi1e5:worldi2ee";
336    expected = "{\"hello\":1,\"world\":2}";
337    if( ( val = testJSONSnippet( benc_str, expected ) ) )
338        return val;
339
340    benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3eee";
341    expected = "{\"foo\":[1,2,3],\"hello\":1,\"world\":2}";
342    if( ( val = testJSONSnippet( benc_str, expected ) ) )
343        return val;
344
345    benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3ed1:ai0eeee";
346    expected = "{\"foo\":[1,2,3,{\"a\":0}],\"hello\":1,\"world\":2}";
347    if( ( val = testJSONSnippet( benc_str, expected ) ) )
348        return val;
349
350    benc_str = "d4:argsd6:statusle7:status2lee6:result7:successe";
351    expected =
352        "{\"args\":{\"status\":[],\"status2\":[]},\"result\":\"success\"}";
353    if( ( val = testJSONSnippet( benc_str, expected ) ) )
354        return val;
355
356    return 0;
357}
358
359static int
360testMerge( void )
361{
362    tr_benc dest, src;
363    int64_t i;
364    const char * s;
365
366    /* initial dictionary (default values)  */
367    tr_bencInitDict( &dest, 10 );
368    tr_bencDictAddInt( &dest, "i1", 1 );
369    tr_bencDictAddInt( &dest, "i2", 2 );
370    tr_bencDictAddInt( &dest, "i4", -35 ); /* remains untouched */
371    tr_bencDictAddStr( &dest, "s5", "abc" );
372    tr_bencDictAddStr( &dest, "s6", "def" );
373    tr_bencDictAddStr( &dest, "s7", "127.0.0.1" ); /* remains untouched */
374
375    /* new dictionary, will overwrite items in dest  */
376    tr_bencInitDict( &src, 10 );
377    tr_bencDictAddInt( &src, "i1", 1 );     /* same value */
378    tr_bencDictAddInt( &src, "i2", 4 );     /* new value */
379    tr_bencDictAddInt( &src, "i3", 3 );     /* new key:value */
380    tr_bencDictAddStr( &src, "s5", "abc" ); /* same value */
381    tr_bencDictAddStr( &src, "s6", "xyz" ); /* new value */
382    tr_bencDictAddStr( &src, "s8", "ghi" ); /* new key:value */
383
384    tr_bencMergeDicts( &dest, /*const*/ &src );
385
386    check( tr_bencDictFindInt( &dest, "i1", &i ));
387    check_int_eq (1, i);
388    check( tr_bencDictFindInt( &dest, "i2", &i ));
389    check_int_eq (4, i);
390    check( tr_bencDictFindInt( &dest, "i3", &i ));
391    check_int_eq (3, i);
392    check( tr_bencDictFindInt( &dest, "i4", &i ));
393    check_int_eq (-35, i);
394    check( tr_bencDictFindStr( &dest, "s5", &s ));
395    check_streq ("abc", s);
396    check( tr_bencDictFindStr( &dest, "s6", &s ));
397    check_streq ("xyz", s);
398    check( tr_bencDictFindStr( &dest, "s7", &s ));
399    check_streq ("127.0.0.1", s);
400    check( tr_bencDictFindStr( &dest, "s8", &s ));
401    check_streq ("ghi", s);
402
403    tr_bencFree( &dest );
404    tr_bencFree( &src );
405    return 0;
406}
407
408static int
409testStackSmash( void )
410{
411    int             i;
412    int             len;
413    int             err;
414    uint8_t *       in;
415    const uint8_t * end;
416    tr_benc         val;
417    char *          saved;
418    const int       depth = STACK_SMASH_DEPTH;
419
420    in = tr_new( uint8_t, depth * 2 + 1 );
421    for( i = 0; i < depth; ++i )
422    {
423        in[i] = 'l';
424        in[depth + i] = 'e';
425    }
426    in[depth * 2] = '\0';
427    err = tr_bencParse( in, in + ( depth * 2 ), &val, &end );
428    check( !err );
429    check( end == in + ( depth * 2 ) );
430    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
431    check_streq ((char*)in, saved);
432    tr_free( in );
433    tr_free( saved );
434    tr_bencFree( &val );
435
436    return 0;
437}
438
439static int
440testBool( void )
441{
442    tr_benc top;
443    int64_t intVal;
444    bool boolVal;
445
446    tr_bencInitDict( &top, 0 );
447
448    tr_bencDictAddBool( &top, "key1", false );
449    tr_bencDictAddBool( &top, "key2", 0 );
450    tr_bencDictAddInt ( &top, "key3", true );
451    tr_bencDictAddInt ( &top, "key4", 1 );
452    check( tr_bencDictFindBool( &top, "key1", &boolVal ) );
453    check( !boolVal );
454    check( tr_bencDictFindBool( &top, "key2", &boolVal ) );
455    check( !boolVal );
456    check( tr_bencDictFindBool( &top, "key3", &boolVal ) );
457    check( boolVal );
458    check( tr_bencDictFindBool( &top, "key4", &boolVal ) );
459    check( boolVal );
460    check( tr_bencDictFindInt( &top, "key1", &intVal ) );
461    check( !intVal);
462    check( tr_bencDictFindInt( &top, "key2", &intVal ) );
463    check( !intVal );
464    check( tr_bencDictFindInt( &top, "key3", &intVal ) );
465    check( intVal );
466    check( tr_bencDictFindInt( &top, "key4", &intVal ) );
467    check( intVal );
468
469    tr_bencFree( &top );
470    return 0;
471}
472
473static int
474testParse2( void )
475{
476    tr_benc top;
477    tr_benc top2;
478    int64_t intVal;
479    const char * strVal;
480    double realVal;
481    bool boolVal;
482    int len;
483    char * benc;
484    const uint8_t * end;
485
486    tr_bencInitDict( &top, 0 );
487    tr_bencDictAddBool( &top, "this-is-a-bool", true );
488    tr_bencDictAddInt( &top, "this-is-an-int", 1234 );
489    tr_bencDictAddReal( &top, "this-is-a-real", 0.5 );
490    tr_bencDictAddStr( &top, "this-is-a-string", "this-is-a-string" );
491
492    benc = tr_bencToStr( &top, TR_FMT_BENC, &len );
493    check_streq( "d14:this-is-a-booli1e14:this-is-a-real8:0.50000016:this-is-a-string16:this-is-a-string14:this-is-an-inti1234ee", benc );
494    check( !tr_bencParse( benc, benc+len, &top2, &end ) );
495    check( (char*)end == benc + len );
496    check( tr_bencIsDict( &top2 ) );
497    check( tr_bencDictFindInt( &top, "this-is-an-int", &intVal ) );
498    check_int_eq (1234, intVal);
499    check( tr_bencDictFindBool( &top, "this-is-a-bool", &boolVal ) );
500    check( boolVal == true );
501    check( tr_bencDictFindStr( &top, "this-is-a-string", &strVal ) );
502    check_streq ("this-is-a-string", strVal);
503    check( tr_bencDictFindReal( &top, "this-is-a-real", &realVal ) );
504    check_int_eq (50, (int)(realVal*100));
505
506    tr_bencFree( &top2 );
507    tr_free( benc );
508    tr_bencFree( &top );
509
510    return 0;
511}
512
513int
514main( void )
515{
516    static const testFunc tests[] = {
517	testInt, testStr, testParse, testJSON, testMerge, testBool,
518	testParse2, testStackSmash,
519    };
520
521    return runTests(tests, NUM_TESTS(tests));
522}
523