source: trunk/libtransmission/bencode.c @ 7590

Last change on this file since 7590 was 7590, checked in by charles, 12 years ago

(trunk libT) inline the tr_bencIs*() utility functions

  • Property svn:keywords set to Date Rev Author Id
File size: 34.8 KB
Line 
1/*
2 * This file Copyright (C) 2008 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: bencode.c 7590 2009-01-03 00:11:31Z charles $
11 */
12
13#include <assert.h>
14#include <ctype.h> /* isdigit, isprint, isspace */
15#include <errno.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include <locale.h>
21
22#include <event.h> /* evbuffer */
23
24#include "ConvertUTF.h"
25
26#include "transmission.h"
27#include "bencode.h"
28#include "json.h"
29#include "list.h"
30#include "ptrarray.h"
31#include "utils.h" /* tr_new(), tr_free() */
32
33/**
34***
35**/
36
37static tr_bool
38isContainer( const tr_benc * val )
39{
40    return tr_bencIsList( val ) || tr_bencIsDict( val );
41}
42
43static tr_bool
44isSomething( const tr_benc * val )
45{
46    return isContainer( val ) || tr_bencIsInt( val ) || tr_bencIsString( val );
47}
48
49static void
50tr_bencInit( tr_benc * val,
51             int       type )
52{
53    memset( val, 0, sizeof( *val ) );
54    val->type = type;
55}
56
57/***
58****  tr_bencParse()
59****  tr_bencLoad()
60***/
61
62/**
63 * The initial i and trailing e are beginning and ending delimiters.
64 * You can have negative numbers such as i-3e. You cannot prefix the
65 * number with a zero such as i04e. However, i0e is valid.
66 * Example: i3e represents the integer "3"
67 * NOTE: The maximum number of bit of this integer is unspecified,
68 * but to handle it as a signed 64bit integer is mandatory to handle
69 * "large files" aka .torrent for more that 4Gbyte
70 */
71int
72tr_bencParseInt( const uint8_t *  buf,
73                 const uint8_t *  bufend,
74                 const uint8_t ** setme_end,
75                 int64_t *        setme_val )
76{
77    int          err = 0;
78    char *       endptr;
79    const void * begin;
80    const void * end;
81    int64_t      val;
82
83    if( buf >= bufend )
84        return EILSEQ;
85    if( *buf != 'i' )
86        return EILSEQ;
87
88    begin = buf + 1;
89    end = memchr( begin, 'e', ( bufend - buf ) - 1 );
90    if( end == NULL )
91        return EILSEQ;
92
93    errno = 0;
94    val = evutil_strtoll( begin, &endptr, 10 );
95    if( errno || ( endptr != end ) ) /* incomplete parse */
96        err = EILSEQ;
97    else if( val && *(const char*)begin == '0' ) /* no leading zeroes! */
98        err = EILSEQ;
99    else
100    {
101        *setme_end = (const uint8_t*)end + 1;
102        *setme_val = val;
103    }
104
105    return err;
106}
107
108/**
109 * Byte strings are encoded as follows:
110 * <string length encoded in base ten ASCII>:<string data>
111 * Note that there is no constant beginning delimiter, and no ending delimiter.
112 * Example: 4:spam represents the string "spam"
113 */
114int
115tr_bencParseStr( const uint8_t *  buf,
116                 const uint8_t *  bufend,
117                 const uint8_t ** setme_end,
118                 const uint8_t ** setme_str,
119                 size_t *         setme_strlen )
120{
121    size_t       len;
122    const void * end;
123    char *       endptr;
124
125    if( buf >= bufend )
126        return EILSEQ;
127
128    if( !isdigit( *buf  ) )
129        return EILSEQ;
130
131    end = memchr( buf, ':', bufend - buf );
132    if( end == NULL )
133        return EILSEQ;
134
135    errno = 0;
136    len = strtoul( (const char*)buf, &endptr, 10 );
137    if( errno || endptr != end )
138        return EILSEQ;
139
140    if( (const uint8_t*)end + 1 + len > bufend )
141        return EILSEQ;
142
143    *setme_end = (const uint8_t*)end + 1 + len;
144    *setme_str = (const uint8_t*)end + 1;
145    *setme_strlen = len;
146    return 0;
147}
148
149/* set to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
150#define LIST_SIZE 8 /* number of items to increment list/dict buffer by */
151
152static int
153makeroom( tr_benc * val,
154          size_t    count )
155{
156    assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
157
158    if( val->val.l.count + count > val->val.l.alloc )
159    {
160        /* We need a bigger boat */
161        const int len = val->val.l.alloc + count +
162                        ( count % LIST_SIZE ? LIST_SIZE -
163                          ( count % LIST_SIZE ) : 0 );
164        void *    new = realloc( val->val.l.vals, len * sizeof( tr_benc ) );
165        if( NULL == new )
166            return 1;
167
168        val->val.l.alloc = len;
169        val->val.l.vals  = new;
170    }
171
172    return 0;
173}
174
175static tr_benc*
176getNode( tr_benc *     top,
177         tr_ptrArray * parentStack,
178         int           type )
179{
180    tr_benc * parent;
181
182    assert( top );
183    assert( parentStack );
184
185    if( tr_ptrArrayEmpty( parentStack ) )
186        return top;
187
188    parent = tr_ptrArrayBack( parentStack );
189    assert( parent );
190
191    /* dictionary keys must be strings */
192    if( ( parent->type == TYPE_DICT )
193      && ( type != TYPE_STR )
194      && ( !( parent->val.l.count % 2 ) ) )
195        return NULL;
196
197    makeroom( parent, 1 );
198    return parent->val.l.vals + parent->val.l.count++;
199}
200
201/**
202 * This function's previous recursive implementation was
203 * easier to read, but was vulnerable to a smash-stacking
204 * attack via maliciously-crafted bencoded data. (#667)
205 */
206static int
207tr_bencParseImpl( const void *     buf_in,
208                  const void *     bufend_in,
209                  tr_benc *        top,
210                  tr_ptrArray *    parentStack,
211                  const uint8_t ** setme_end )
212{
213    int             err;
214    const uint8_t * buf = buf_in;
215    const uint8_t * bufend = bufend_in;
216
217    tr_bencInit( top, 0 );
218
219    while( buf != bufend )
220    {
221        if( buf > bufend ) /* no more text to parse... */
222            return 1;
223
224        if( *buf == 'i' ) /* int */
225        {
226            int64_t         val;
227            const uint8_t * end;
228            tr_benc *       node;
229
230            if( ( err = tr_bencParseInt( buf, bufend, &end, &val ) ) )
231                return err;
232
233            node = getNode( top, parentStack, TYPE_INT );
234            if( !node )
235                return EILSEQ;
236
237            tr_bencInitInt( node, val );
238            buf = end;
239
240            if( tr_ptrArrayEmpty( parentStack ) )
241                break;
242        }
243        else if( *buf == 'l' ) /* list */
244        {
245            tr_benc * node = getNode( top, parentStack, TYPE_LIST );
246            if( !node )
247                return EILSEQ;
248            tr_bencInit( node, TYPE_LIST );
249            tr_ptrArrayAppend( parentStack, node );
250            ++buf;
251        }
252        else if( *buf == 'd' ) /* dict */
253        {
254            tr_benc * node = getNode( top, parentStack, TYPE_DICT );
255            if( !node )
256                return EILSEQ;
257            tr_bencInit( node, TYPE_DICT );
258            tr_ptrArrayAppend( parentStack, node );
259            ++buf;
260        }
261        else if( *buf == 'e' ) /* end of list or dict */
262        {
263            tr_benc * node;
264            ++buf;
265            if( tr_ptrArrayEmpty( parentStack ) )
266                return EILSEQ;
267
268            node = tr_ptrArrayBack( parentStack );
269            if( tr_bencIsDict( node ) && ( node->val.l.count % 2 ) )
270            {
271                /* odd # of children in dict */
272                tr_bencFree( &node->val.l.vals[--node->val.l.count] );
273                return EILSEQ;
274            }
275
276            tr_ptrArrayPop( parentStack );
277            if( tr_ptrArrayEmpty( parentStack ) )
278                break;
279        }
280        else if( isdigit( *buf ) ) /* string? */
281        {
282            const uint8_t * end;
283            const uint8_t * str;
284            size_t          str_len;
285            tr_benc *       node;
286
287            if( ( err = tr_bencParseStr( buf, bufend, &end, &str, &str_len ) ) )
288                return err;
289
290            node = getNode( top, parentStack, TYPE_STR );
291            if( !node )
292                return EILSEQ;
293
294            tr_bencInitStr( node, str, str_len );
295            buf = end;
296
297            if( tr_ptrArrayEmpty( parentStack ) )
298                break;
299        }
300        else /* invalid bencoded text... march past it */
301        {
302            ++buf;
303        }
304    }
305
306    err = !isSomething( top ) || !tr_ptrArrayEmpty( parentStack );
307
308    if( !err && setme_end )
309        *setme_end = buf;
310
311    return err;
312}
313
314int
315tr_bencParse( const void *     buf,
316              const void *     end,
317              tr_benc *        top,
318              const uint8_t ** setme_end )
319{
320    int           err;
321    tr_ptrArray   parentStack = TR_PTR_ARRAY_INIT;
322
323    top->type = 0; /* set to `uninitialized' */
324    err = tr_bencParseImpl( buf, end, top, &parentStack, setme_end );
325    if( err )
326        tr_bencFree( top );
327
328    tr_ptrArrayDestruct( &parentStack, NULL );
329    return err;
330}
331
332int
333tr_bencLoad( const void * buf_in,
334             size_t       buflen,
335             tr_benc *    setme_benc,
336             char **      setme_end )
337{
338    const uint8_t * buf = buf_in;
339    const uint8_t * end;
340    const int       ret = tr_bencParse( buf, buf + buflen, setme_benc, &end );
341
342    if( !ret && setme_end )
343        *setme_end = (char*) end;
344    return ret;
345}
346
347/***
348****
349***/
350
351static int
352dictIndexOf( const tr_benc * val,
353             const char *    key )
354{
355    if( tr_bencIsDict( val ) )
356    {
357        size_t       i;
358        const size_t len = strlen( key );
359
360        for( i = 0; ( i + 1 ) < val->val.l.count; i += 2 )
361        {
362            const tr_benc * child = val->val.l.vals + i;
363
364            if( ( child->type == TYPE_STR )
365              && ( child->val.s.i == len )
366              && !memcmp( child->val.s.s, key, len ) )
367                return i;
368        }
369    }
370
371    return -1;
372}
373
374tr_benc *
375tr_bencDictFind( tr_benc * val, const char * key )
376{
377    const int i = dictIndexOf( val, key );
378
379    return i < 0 ? NULL : &val->val.l.vals[i + 1];
380}
381
382static tr_benc*
383tr_bencDictFindType( tr_benc *    val,
384                     const char * key,
385                     int          type )
386{
387    tr_benc * ret = tr_bencDictFind( val, key );
388
389    return ( ret && ( ret->type == type ) ) ? ret : NULL;
390}
391
392size_t
393tr_bencListSize( const tr_benc * list )
394{
395    return tr_bencIsList( list ) ? list->val.l.count : 0;
396}
397
398tr_benc*
399tr_bencListChild( tr_benc * val,
400                  size_t    i )
401{
402    tr_benc * ret = NULL;
403
404    if( tr_bencIsList( val ) && ( i < val->val.l.count ) )
405        ret = val->val.l.vals + i;
406    return ret;
407}
408
409tr_bool
410tr_bencGetInt( const tr_benc * val,
411               int64_t *       setme )
412{
413    const int success = tr_bencIsInt( val );
414
415    if( success && setme )
416        *setme = val->val.i;
417
418    return success;
419}
420
421tr_bool
422tr_bencGetStr( const tr_benc * val,
423               const char **   setme )
424{
425    const int success = tr_bencIsString( val );
426
427    if( success )
428        *setme = val->val.s.s;
429    return success;
430}
431
432tr_bool
433tr_bencDictFindInt( tr_benc * dict, const char * key, int64_t * setme )
434{
435    tr_bool found = FALSE;
436    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_INT );
437
438    if( child )
439        found = tr_bencGetInt( child, setme );
440
441    return found;
442}
443
444tr_bool
445tr_bencDictFindDouble( tr_benc * dict, const char * key, double * setme )
446{
447    const char * str;
448    const tr_bool success = tr_bencDictFindStr( dict, key, &str );
449
450    if( success && setme )
451        *setme = strtod( str, NULL );
452
453    return success;
454}
455
456tr_bool
457tr_bencDictFindList( tr_benc * dict, const char * key, tr_benc ** setme )
458{
459    tr_bool found = FALSE;
460    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_LIST );
461
462    if( child )
463    {
464        if( setme != NULL )
465            *setme = child;
466        found = TRUE;
467    }
468
469    return found;
470}
471
472tr_bool
473tr_bencDictFindDict( tr_benc * dict, const char * key, tr_benc ** setme )
474{
475    tr_bool found = FALSE;
476    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_DICT );
477
478    if( child )
479    {
480        if( setme != NULL )
481            *setme = child;
482        found = TRUE;
483    }
484
485    return found;
486}
487
488tr_bool
489tr_bencDictFindStr( tr_benc *  dict, const char *  key, const char ** setme )
490{
491    tr_bool found = FALSE;
492    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR );
493
494    if( child )
495    {
496        if( setme )
497            *setme = child->val.s.s;
498        found = TRUE;
499    }
500
501    return found;
502}
503
504tr_bool
505tr_bencDictFindRaw( tr_benc         * dict,
506                    const char      * key,
507                    const uint8_t  ** setme_raw,
508                    size_t          * setme_len )
509{
510    tr_bool found = FALSE;
511    tr_benc * child = tr_bencDictFindType( dict, key, TYPE_STR );
512
513    if( child )
514    {
515        *setme_raw = (uint8_t*) child->val.s.s;
516        *setme_len = child->val.s.i;
517        found = TRUE;
518    }
519
520    return found;
521}
522
523/***
524****
525***/
526
527void
528tr_bencInitRaw( tr_benc *    val,
529                const void * src,
530                size_t       byteCount )
531{
532    tr_bencInit( val, TYPE_STR );
533    val->val.s.i = byteCount;
534    val->val.s.s = tr_memdup( src, byteCount );
535}
536
537void
538tr_bencInitStr( tr_benc *    val,
539                const void * str,
540                int          len )
541{
542    tr_bencInit( val, TYPE_STR );
543
544    val->val.s.s = tr_strndup( str, len );
545
546    if( val->val.s.s == NULL )
547        val->val.s.i = 0;
548    else if( len < 0 )
549        val->val.s.i = strlen( val->val.s.s );
550    else
551        val->val.s.i = len;
552}
553
554void
555tr_bencInitInt( tr_benc * val,
556                int64_t   num )
557{
558    tr_bencInit( val, TYPE_INT );
559    val->val.i = num;
560}
561
562int
563tr_bencInitList( tr_benc * val,
564                 size_t    reserveCount )
565{
566    tr_bencInit( val, TYPE_LIST );
567    return tr_bencListReserve( val, reserveCount );
568}
569
570int
571tr_bencListReserve( tr_benc * val,
572                    size_t    count )
573{
574    assert( tr_bencIsList( val ) );
575    return makeroom( val, count );
576}
577
578int
579tr_bencInitDict( tr_benc * val,
580                 size_t    reserveCount )
581{
582    tr_bencInit( val, TYPE_DICT );
583    return tr_bencDictReserve( val, reserveCount );
584}
585
586int
587tr_bencDictReserve( tr_benc * val,
588                    size_t    reserveCount )
589{
590    assert( tr_bencIsDict( val ) );
591    return makeroom( val, reserveCount * 2 );
592}
593
594tr_benc *
595tr_bencListAdd( tr_benc * list )
596{
597    tr_benc * item;
598
599    assert( tr_bencIsList( list ) );
600
601    if( list->val.l.count == list->val.l.alloc )
602        tr_bencListReserve( list, LIST_SIZE );
603
604    assert( list->val.l.count < list->val.l.alloc );
605
606    item = &list->val.l.vals[list->val.l.count];
607    list->val.l.count++;
608    tr_bencInit( item, TYPE_INT );
609
610    return item;
611}
612
613tr_benc *
614tr_bencListAddInt( tr_benc * list,
615                   int64_t   val )
616{
617    tr_benc * node = tr_bencListAdd( list );
618
619    tr_bencInitInt( node, val );
620    return node;
621}
622
623tr_benc *
624tr_bencListAddStr( tr_benc *    list,
625                   const char * val )
626{
627    tr_benc * node = tr_bencListAdd( list );
628
629    tr_bencInitStr( node, val, -1 );
630    return node;
631}
632
633tr_benc*
634tr_bencListAddList( tr_benc * list,
635                    size_t    reserveCount )
636{
637    tr_benc * child = tr_bencListAdd( list );
638
639    tr_bencInitList( child, reserveCount );
640    return child;
641}
642
643tr_benc*
644tr_bencListAddDict( tr_benc * list,
645                    size_t    reserveCount )
646{
647    tr_benc * child = tr_bencListAdd( list );
648
649    tr_bencInitDict( child, reserveCount );
650    return child;
651}
652
653tr_benc *
654tr_bencDictAdd( tr_benc *    dict,
655                const char * key )
656{
657    tr_benc * keyval, * itemval;
658
659    assert( tr_bencIsDict( dict ) );
660    if( dict->val.l.count + 2 > dict->val.l.alloc )
661        makeroom( dict, 2 );
662    assert( dict->val.l.count + 2 <= dict->val.l.alloc );
663
664    keyval = dict->val.l.vals + dict->val.l.count++;
665    tr_bencInitStr( keyval, key, -1 );
666
667    itemval = dict->val.l.vals + dict->val.l.count++;
668    tr_bencInit( itemval, TYPE_INT );
669
670    return itemval;
671}
672
673tr_benc*
674tr_bencDictAddInt( tr_benc *    dict,
675                   const char * key,
676                   int64_t      val )
677{
678    tr_benc * child;
679
680    /* see if it already exists, and if so, try to reuse it */
681    if(( child = tr_bencDictFind( dict, key ))) {
682        if( !tr_bencIsInt( child ) ) {
683            tr_bencDictRemove( dict, key );
684            child = NULL;
685        }
686    }
687
688    /* if it doesn't exist, create it */
689    if( child == NULL )
690        child = tr_bencDictAdd( dict, key );
691
692    /* set it */
693    tr_bencInitInt( child, val );
694
695    return child;
696}
697
698tr_benc*
699tr_bencDictAddStr( tr_benc * dict, const char * key, const char * val )
700{
701    tr_benc * child;
702
703    /* see if it already exists, and if so, try to reuse it */
704    if(( child = tr_bencDictFind( dict, key ))) {
705        if( tr_bencIsString( child ) )
706            tr_free( child->val.s.s );
707        else {
708            tr_bencDictRemove( dict, key );
709            child = NULL;
710        }
711    }
712
713    /* if it doesn't exist, create it */
714    if( child == NULL )
715        child = tr_bencDictAdd( dict, key );
716
717    /* set it */
718    tr_bencInitStr( child, val, -1 );
719
720    return child;
721}
722
723tr_benc*
724tr_bencDictAddDouble( tr_benc *    dict,
725                      const char * key,
726                      double       d )
727{
728    char buf[128];
729    char * locale;
730
731    /* the json spec requires a '.' decimal point regardless of locale */
732    locale = tr_strdup( setlocale ( LC_NUMERIC, NULL ) );
733    setlocale( LC_NUMERIC, "POSIX" );
734    tr_snprintf( buf, sizeof( buf ), "%f", d );
735    setlocale( LC_NUMERIC, locale );
736    tr_free( locale );
737
738    return tr_bencDictAddStr( dict, key, buf );
739}
740
741tr_benc*
742tr_bencDictAddList( tr_benc *    dict,
743                    const char * key,
744                    size_t       reserveCount )
745{
746    tr_benc * child = tr_bencDictAdd( dict, key );
747
748    tr_bencInitList( child, reserveCount );
749    return child;
750}
751
752tr_benc*
753tr_bencDictAddDict( tr_benc *    dict,
754                    const char * key,
755                    size_t       reserveCount )
756{
757    tr_benc * child = tr_bencDictAdd( dict, key );
758
759    tr_bencInitDict( child, reserveCount );
760    return child;
761}
762
763tr_benc*
764tr_bencDictAddRaw( tr_benc *    dict,
765                   const char * key,
766                   const void * src,
767                   size_t       len )
768{
769    tr_benc * child = tr_bencDictAdd( dict, key );
770
771    tr_bencInitRaw( child, src, len );
772    return child;
773}
774
775int
776tr_bencDictRemove( tr_benc *    dict,
777                   const char * key )
778{
779    int i = dictIndexOf( dict, key );
780
781    if( i >= 0 )
782    {
783        const int n = dict->val.l.count;
784        tr_bencFree( &dict->val.l.vals[i] );
785        tr_bencFree( &dict->val.l.vals[i + 1] );
786        if( i + 2 < n )
787        {
788            dict->val.l.vals[i]   = dict->val.l.vals[n - 2];
789            dict->val.l.vals[i + 1] = dict->val.l.vals[n - 1];
790        }
791        dict->val.l.count -= 2;
792    }
793    return i >= 0; /* return true if found */
794}
795
796/***
797****  BENC WALKING
798***/
799
800struct KeyIndex
801{
802    const char *  key;
803    int           index;
804};
805
806static int
807compareKeyIndex( const void * va,
808                 const void * vb )
809{
810    const struct KeyIndex * a = va;
811    const struct KeyIndex * b = vb;
812
813    return strcmp( a->key, b->key );
814}
815
816struct SaveNode
817{
818    const tr_benc *  val;
819    int              valIsVisited;
820    int              childCount;
821    int              childIndex;
822    int *            children;
823};
824
825static struct SaveNode*
826nodeNewDict( const tr_benc * val )
827{
828    int               i, j;
829    int               nKeys;
830    struct SaveNode * node;
831    struct KeyIndex * indices;
832
833    assert( tr_bencIsDict( val ) );
834
835    nKeys = val->val.l.count / 2;
836    node = tr_new0( struct SaveNode, 1 );
837    node->val = val;
838    node->children = tr_new0( int, nKeys * 2 );
839
840    /* ugh, a dictionary's children have to be sorted by key... */
841    indices = tr_new( struct KeyIndex, nKeys );
842    for( i = j = 0; i < ( nKeys * 2 ); i += 2, ++j )
843    {
844        indices[j].key = val->val.l.vals[i].val.s.s;
845        indices[j].index = i;
846    }
847    qsort( indices, j, sizeof( struct KeyIndex ), compareKeyIndex );
848    for( i = 0; i < j; ++i )
849    {
850        const int index = indices[i].index;
851        node->children[node->childCount++] = index;
852        node->children[node->childCount++] = index + 1;
853    }
854
855    assert( node->childCount == nKeys * 2 );
856    tr_free( indices );
857    return node;
858}
859
860static struct SaveNode*
861nodeNewList( const tr_benc * val )
862{
863    int               i, n;
864    struct SaveNode * node;
865
866    assert( tr_bencIsList( val ) );
867
868    n = val->val.l.count;
869    node = tr_new0( struct SaveNode, 1 );
870    node->val = val;
871    node->childCount = n;
872    node->children = tr_new0( int, n );
873    for( i = 0; i < n; ++i ) /* a list's children don't need to be reordered */
874        node->children[i] = i;
875
876    return node;
877}
878
879static struct SaveNode*
880nodeNewLeaf( const tr_benc * val )
881{
882    struct SaveNode * node;
883
884    assert( !isContainer( val ) );
885
886    node = tr_new0( struct SaveNode, 1 );
887    node->val = val;
888    return node;
889}
890
891static struct SaveNode*
892nodeNew( const tr_benc * val )
893{
894    struct SaveNode * node;
895
896    if( tr_bencIsList( val ) )
897        node = nodeNewList( val );
898    else if( tr_bencIsDict( val ) )
899        node = nodeNewDict( val );
900    else
901        node = nodeNewLeaf( val );
902
903    return node;
904}
905
906typedef void ( *BencWalkFunc )( const tr_benc * val, void * user_data );
907
908struct WalkFuncs
909{
910    BencWalkFunc    intFunc;
911    BencWalkFunc    stringFunc;
912    BencWalkFunc    dictBeginFunc;
913    BencWalkFunc    listBeginFunc;
914    BencWalkFunc    containerEndFunc;
915};
916
917/**
918 * This function's previous recursive implementation was
919 * easier to read, but was vulnerable to a smash-stacking
920 * attack via maliciously-crafted bencoded data. (#667)
921 */
922static void
923bencWalk( const tr_benc *    top,
924          struct WalkFuncs * walkFuncs,
925          void *             user_data )
926{
927    tr_ptrArray stack = TR_PTR_ARRAY_INIT;
928
929    tr_ptrArrayAppend( &stack, nodeNew( top ) );
930
931    while( !tr_ptrArrayEmpty( &stack ) )
932    {
933        struct SaveNode * node = tr_ptrArrayBack( &stack );
934        const tr_benc *   val;
935
936        if( !node->valIsVisited )
937        {
938            val = node->val;
939            node->valIsVisited = TRUE;
940        }
941        else if( node->childIndex < node->childCount )
942        {
943            const int index = node->children[node->childIndex++];
944            val = node->val->val.l.vals +  index;
945        }
946        else /* done with this node */
947        {
948            if( isContainer( node->val ) )
949                walkFuncs->containerEndFunc( node->val, user_data );
950            tr_ptrArrayPop( &stack );
951            tr_free( node->children );
952            tr_free( node );
953            continue;
954        }
955
956        if( val ) switch( val->type )
957            {
958                case TYPE_INT:
959                    walkFuncs->intFunc( val, user_data );
960                    break;
961
962                case TYPE_STR:
963                    walkFuncs->stringFunc( val, user_data );
964                    break;
965
966                case TYPE_LIST:
967                    if( val != node->val )
968                        tr_ptrArrayAppend( &stack, nodeNew( val ) );
969                    else
970                        walkFuncs->listBeginFunc( val, user_data );
971                    break;
972
973                case TYPE_DICT:
974                    if( val != node->val )
975                        tr_ptrArrayAppend( &stack, nodeNew( val ) );
976                    else
977                        walkFuncs->dictBeginFunc( val, user_data );
978                    break;
979
980                default:
981                    /* did caller give us an uninitialized val? */
982                    tr_err( _( "Invalid metadata" ) );
983                    break;
984            }
985    }
986
987    tr_ptrArrayDestruct( &stack, NULL );
988}
989
990/****
991*****
992****/
993
994static void
995saveIntFunc( const tr_benc * val,
996             void *          evbuf )
997{
998    evbuffer_add_printf( evbuf, "i%" PRId64 "e", val->val.i );
999}
1000
1001static void
1002saveStringFunc( const tr_benc * val,
1003                void *          vevbuf )
1004{
1005    struct evbuffer * evbuf = vevbuf;
1006
1007    evbuffer_add_printf( evbuf, "%lu:", (unsigned long)val->val.s.i );
1008    evbuffer_add( evbuf, val->val.s.s, val->val.s.i );
1009}
1010
1011static void
1012saveDictBeginFunc( const tr_benc * val UNUSED,
1013                   void *              evbuf )
1014{
1015    evbuffer_add_printf( evbuf, "d" );
1016}
1017
1018static void
1019saveListBeginFunc( const tr_benc * val UNUSED,
1020                   void *              evbuf )
1021{
1022    evbuffer_add_printf( evbuf, "l" );
1023}
1024
1025static void
1026saveContainerEndFunc( const tr_benc * val UNUSED,
1027                      void *              evbuf )
1028{
1029    evbuffer_add_printf( evbuf, "e" );
1030}
1031
1032char*
1033tr_bencSave( const tr_benc * top,
1034             int *           len )
1035{
1036    char *            ret;
1037    struct WalkFuncs  walkFuncs;
1038    struct evbuffer * out = tr_getBuffer( );
1039
1040    walkFuncs.intFunc = saveIntFunc;
1041    walkFuncs.stringFunc = saveStringFunc;
1042    walkFuncs.dictBeginFunc = saveDictBeginFunc;
1043    walkFuncs.listBeginFunc = saveListBeginFunc;
1044    walkFuncs.containerEndFunc = saveContainerEndFunc;
1045    bencWalk( top, &walkFuncs, out );
1046
1047    if( len )
1048        *len = EVBUFFER_LENGTH( out );
1049    ret = tr_strndup( EVBUFFER_DATA( out ), EVBUFFER_LENGTH( out ) );
1050
1051    tr_releaseBuffer( out );
1052    return ret;
1053}
1054
1055/***
1056****
1057***/
1058
1059static void
1060freeDummyFunc( const tr_benc * val UNUSED,
1061               void * buf          UNUSED  )
1062{}
1063
1064static void
1065freeStringFunc( const tr_benc * val,
1066                void *          freeme )
1067{
1068    tr_ptrArrayAppend( freeme, val->val.s.s );
1069}
1070
1071static void
1072freeContainerBeginFunc( const tr_benc * val,
1073                        void *          freeme )
1074{
1075    tr_ptrArrayAppend( freeme, val->val.l.vals );
1076}
1077
1078void
1079tr_bencFree( tr_benc * val )
1080{
1081    if( val && val->type )
1082    {
1083        tr_ptrArray a = TR_PTR_ARRAY_INIT;
1084        struct WalkFuncs walkFuncs;
1085
1086        walkFuncs.intFunc = freeDummyFunc;
1087        walkFuncs.stringFunc = freeStringFunc;
1088        walkFuncs.dictBeginFunc = freeContainerBeginFunc;
1089        walkFuncs.listBeginFunc = freeContainerBeginFunc;
1090        walkFuncs.containerEndFunc = freeDummyFunc;
1091        bencWalk( val, &walkFuncs, &a );
1092
1093        tr_ptrArrayDestruct( &a, tr_free );
1094    }
1095}
1096
1097/***
1098****
1099***/
1100
1101struct ParentState
1102{
1103    int    bencType;
1104    int    childIndex;
1105    int    childCount;
1106};
1107
1108struct jsonWalk
1109{
1110    tr_list *          parents;
1111    struct evbuffer *  out;
1112};
1113
1114static void
1115jsonIndent( struct jsonWalk * data )
1116{
1117    const int width = tr_list_size( data->parents ) * 4;
1118
1119    evbuffer_add_printf( data->out, "\n%*.*s", width, width, " " );
1120}
1121
1122static void
1123jsonChildFunc( struct jsonWalk * data )
1124{
1125    if( data->parents )
1126    {
1127        struct ParentState * parentState = data->parents->data;
1128
1129        switch( parentState->bencType )
1130        {
1131            case TYPE_DICT:
1132            {
1133                const int i = parentState->childIndex++;
1134                if( !( i % 2 ) )
1135                    evbuffer_add_printf( data->out, ": " );
1136                else
1137                {
1138                    evbuffer_add_printf( data->out, ", " );
1139                    jsonIndent( data );
1140                }
1141                break;
1142            }
1143
1144            case TYPE_LIST:
1145            {
1146                ++parentState->childIndex;
1147                evbuffer_add_printf( data->out, ", " );
1148                jsonIndent( data );
1149                break;
1150            }
1151
1152            default:
1153                break;
1154        }
1155    }
1156}
1157
1158static void
1159jsonPushParent( struct jsonWalk * data,
1160                const tr_benc *   benc )
1161{
1162    struct ParentState * parentState = tr_new( struct ParentState, 1 );
1163
1164    parentState->bencType = benc->type;
1165    parentState->childIndex = 0;
1166    parentState->childCount = benc->val.l.count;
1167    tr_list_prepend( &data->parents, parentState );
1168}
1169
1170static void
1171jsonPopParent( struct jsonWalk * data )
1172{
1173    tr_free( tr_list_pop_front( &data->parents ) );
1174}
1175
1176static void
1177jsonIntFunc( const tr_benc * val,
1178             void *          vdata )
1179{
1180    struct jsonWalk * data = vdata;
1181
1182    evbuffer_add_printf( data->out, "%" PRId64, val->val.i );
1183    jsonChildFunc( data );
1184}
1185
1186static void
1187jsonStringFunc( const tr_benc * val,
1188                void *          vdata )
1189{
1190    struct jsonWalk *    data = vdata;
1191    const unsigned char *it, *end;
1192
1193    evbuffer_add_printf( data->out, "\"" );
1194    for( it = (const unsigned char*)val->val.s.s, end = it + val->val.s.i;
1195         it != end; ++it )
1196    {
1197        switch( *it )
1198        {
1199            case '/':
1200                evbuffer_add_printf( data->out, "\\/" ); break;
1201
1202            case '\b':
1203                evbuffer_add_printf( data->out, "\\b" ); break;
1204
1205            case '\f':
1206                evbuffer_add_printf( data->out, "\\f" ); break;
1207
1208            case '\n':
1209                evbuffer_add_printf( data->out, "\\n" ); break;
1210
1211            case '\r':
1212                evbuffer_add_printf( data->out, "\\r" ); break;
1213
1214            case '\t':
1215                evbuffer_add_printf( data->out, "\\t" ); break;
1216
1217            case '"':
1218                evbuffer_add_printf( data->out, "\\\"" ); break;
1219
1220            case '\\':
1221                evbuffer_add_printf( data->out, "\\\\" ); break;
1222
1223            default:
1224                if( isascii( *it ) )
1225                {
1226                    /*fprintf( stderr, "[%c]\n", *it );*/
1227                    evbuffer_add_printf( data->out, "%c", *it );
1228                }
1229                else
1230                {
1231                    const UTF8 * tmp = it;
1232                    UTF32        buf = 0;
1233                    UTF32 *      u32 = &buf;
1234                    ConversionResult result = ConvertUTF8toUTF32( &tmp, end, &u32, &buf + 1, 0 );
1235                    if( ( result != conversionOK ) && ( tmp == it ) )
1236                        ++it; /* it's beyond help; skip it */
1237                    else {
1238                        evbuffer_add_printf( data->out, "\\u%04x", buf );
1239                        it = tmp - 1;
1240                    }
1241                    /*fprintf( stderr, "[\\u%04x]\n", buf );*/
1242                }
1243        }
1244    }
1245    evbuffer_add_printf( data->out, "\"" );
1246    jsonChildFunc( data );
1247}
1248
1249static void
1250jsonDictBeginFunc( const tr_benc * val,
1251                   void *          vdata )
1252{
1253    struct jsonWalk * data = vdata;
1254
1255    jsonPushParent( data, val );
1256    evbuffer_add_printf( data->out, "{" );
1257    if( val->val.l.count )
1258        jsonIndent( data );
1259}
1260
1261static void
1262jsonListBeginFunc( const tr_benc * val,
1263                   void *          vdata )
1264{
1265    const size_t      nChildren = tr_bencListSize( val );
1266    struct jsonWalk * data = vdata;
1267
1268    jsonPushParent( data, val );
1269    evbuffer_add_printf( data->out, "[" );
1270    if( nChildren )
1271        jsonIndent( data );
1272}
1273
1274static void
1275jsonContainerEndFunc( const tr_benc * val,
1276                      void *          vdata )
1277{
1278    size_t            i;
1279    struct jsonWalk * data = vdata;
1280    char *            str;
1281    int               emptyContainer = FALSE;
1282
1283    /* trim out the trailing comma, if any */
1284    str = (char*) EVBUFFER_DATA( data->out );
1285    for( i = EVBUFFER_LENGTH( data->out ) - 1; i > 0; --i )
1286    {
1287        if( isspace( str[i] ) ) continue;
1288        if( str[i] == ',' )
1289            EVBUFFER_LENGTH( data->out ) = i;
1290        if( str[i] == '{' || str[i] == '[' )
1291            emptyContainer = TRUE;
1292        break;
1293    }
1294
1295    jsonPopParent( data );
1296    if( !emptyContainer )
1297        jsonIndent( data );
1298    if( tr_bencIsDict( val ) )
1299        evbuffer_add_printf( data->out, "}" );
1300    else /* list */
1301        evbuffer_add_printf( data->out, "]" );
1302    jsonChildFunc( data );
1303}
1304
1305char*
1306tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out )
1307{
1308    struct WalkFuncs walkFuncs;
1309    struct jsonWalk  data;
1310
1311    evbuffer_drain( out, EVBUFFER_LENGTH( out ) );
1312
1313    data.out = out;
1314    data.parents = NULL;
1315
1316    walkFuncs.intFunc = jsonIntFunc;
1317    walkFuncs.stringFunc = jsonStringFunc;
1318    walkFuncs.dictBeginFunc = jsonDictBeginFunc;
1319    walkFuncs.listBeginFunc = jsonListBeginFunc;
1320    walkFuncs.containerEndFunc = jsonContainerEndFunc;
1321
1322    bencWalk( top, &walkFuncs, &data );
1323
1324    if( EVBUFFER_LENGTH( out ) )
1325        evbuffer_add_printf( out, "\n" );
1326
1327    return (char*) EVBUFFER_DATA( out );
1328}
1329
1330/***
1331****
1332***/
1333
1334static size_t
1335tr_bencDictSize( const tr_benc * dict )
1336{
1337    size_t count = 0;
1338
1339    if( tr_bencIsDict( dict ) )
1340        count = dict->val.l.count / 2;
1341
1342    return count;
1343}
1344
1345static tr_bool
1346tr_bencDictChild( const tr_benc * dict, size_t n, const char ** key, const tr_benc ** val )
1347{
1348    tr_bool success = 0;
1349
1350    assert( tr_bencIsDict( dict ) );
1351
1352    if( tr_bencIsDict( dict ) && (n*2)+1 <= dict->val.l.count )
1353    {
1354        tr_benc * k = dict->val.l.vals + (n*2);
1355        tr_benc * v = dict->val.l.vals + (n*2) + 1;
1356        if(( success = tr_bencGetStr( k, key ) && isSomething( v )))
1357            *val = v;
1358    }
1359
1360    return success;
1361}
1362
1363void 
1364tr_bencMergeDicts( tr_benc * target, const tr_benc * source )
1365{
1366    size_t i;
1367    const size_t sourceCount = tr_bencDictSize( source );
1368
1369    assert( tr_bencIsDict( target ) );
1370    assert( tr_bencIsDict( source ) );
1371
1372    for( i=0; i<sourceCount; ++i )
1373    {
1374        const char * key;
1375        const tr_benc * val;
1376
1377        if( tr_bencDictChild( source, i, &key, &val ) )
1378        {
1379            int64_t i64;
1380            const char * str;
1381            tr_benc * t;
1382
1383            if( tr_bencGetInt( val, &i64 ) )
1384            {
1385                tr_bencDictRemove( target, key );
1386                tr_bencDictAddInt( target, key, i64 );
1387            }
1388            else if( tr_bencGetStr( val, &str ) )
1389            {
1390                tr_bencDictRemove( target, key );
1391                tr_bencDictAddStr( target, key, str );
1392            }
1393            else if( tr_bencIsDict( val ) && tr_bencDictFindDict( target, key, &t ) )
1394            {
1395                tr_bencMergeDicts( t, val );
1396            }
1397            else
1398            {
1399           
1400                tr_dbg( "tr_bencMergeDicts skipping \"%s\"", key );
1401            }
1402        }
1403    }
1404}
1405
1406/***
1407****
1408***/ 
1409
1410static int
1411saveFile( const char * filename,
1412          const char * content,
1413          size_t       len )
1414{
1415    int    err = 0;
1416    FILE * out = NULL;
1417
1418    out = fopen( filename, "wb+" );
1419
1420    if( !out )
1421    {
1422        err = errno;
1423        tr_err( _( "Couldn't open \"%1$s\": %2$s" ),
1424                filename, tr_strerror( errno ) );
1425    }
1426    else if( fwrite( content, sizeof( char ), len, out ) != (size_t)len )
1427    {
1428        err = errno;
1429        tr_err( _( "Couldn't save file \"%1$s\": %2$s" ),
1430               filename, tr_strerror( errno ) );
1431    }
1432
1433    if( !err )
1434        tr_dbg( "tr_bencSaveFile saved \"%s\"", filename );
1435    if( out )
1436        fclose( out );
1437    return err;
1438}
1439
1440int
1441tr_bencSaveFile( const char *    filename,
1442                 const tr_benc * b )
1443{
1444    int       len;
1445    char *    content = tr_bencSave( b, &len );
1446    const int err = saveFile( filename, content, len );
1447
1448    tr_free( content );
1449    return err;
1450}
1451
1452int
1453tr_bencSaveJSONFile( const char *    filename,
1454                     const tr_benc * b )
1455{
1456    struct evbuffer * buf = tr_getBuffer( );
1457    const char * json = tr_bencSaveAsJSON( b, buf );
1458    const int err = saveFile( filename, json, EVBUFFER_LENGTH( buf ) );
1459    tr_releaseBuffer( buf );
1460    return err;
1461}
1462
1463/***
1464****
1465***/
1466
1467int
1468tr_bencLoadFile( const char * filename,
1469                 tr_benc *    b )
1470{
1471    int       err;
1472    size_t    contentLen;
1473    uint8_t * content;
1474
1475    content = tr_loadFile( filename, &contentLen );
1476    if( !content )
1477        err = errno;
1478    else
1479        err = tr_bencLoad( content, contentLen, b, NULL );
1480
1481    tr_free( content );
1482    return err;
1483}
1484
1485int
1486tr_bencLoadJSONFile( const char * filename,
1487                     tr_benc *    b )
1488{
1489    int        err;
1490    size_t     contentLen;
1491    uint8_t  * content;
1492
1493    content = tr_loadFile( filename, &contentLen );
1494    if( !content )
1495        err = errno;
1496    else
1497        err = tr_jsonParse( content, contentLen, b, NULL );
1498
1499    tr_free( content );
1500    return err;
1501}
1502
Note: See TracBrowser for help on using the repository browser.