Changeset 2302


Ignore:
Timestamp:
Jul 6, 2007, 8:43:17 PM (15 years ago)
Author:
charles
Message:

Better handling of malformed bencoded strings. Thanks to cluthi81 for reporting this.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/bencode.c

    r2228 r2302  
    2323 *****************************************************************************/
    2424
     25#include <ctype.h> /* for isdigit */
    2526#include "transmission.h"
    2627
     
    5253    char * p, * e, * foo;
    5354
    54     if( NULL == buf || 1 >= len )
    55     {
    56         return 1;
    57     }
    58 
    5955    if( !end )
    6056    {
     
    6359    }
    6460
    65     if( buf[0] == 'i' )
    66     {
    67         int64_t num;
    68 
    69         e = memchr( &buf[1], 'e', len - 1 );
    70         if( NULL == e )
    71         {
     61    for( ;; )
     62    {
     63        if( !buf || len<1 ) /* no more text to parse... */
    7264            return 1;
    73         }
    74 
    75         /* Integer: i1242e */
    76         *e = '\0';
    77         num = strtoll( &buf[1], &p, 10 );
    78         *e = 'e';
    79 
    80         if( p != e )
    81         {
    82             return 1;
    83         }
    84 
    85         tr_bencInitInt( val, num );
    86         *end = p + 1;
    87     }
    88     else if( buf[0] == 'l' || buf[0] == 'd' )
    89     {
    90         /* List: l<item1><item2>e
    91            Dict: d<string1><item1><string2><item2>e
    92            A dictionary is just a special kind of list with an even
    93            count of items, and where even items are strings. */
    94         char * cur;
    95         char   is_dict;
    96         char   str_expected;
    97 
    98         is_dict      = ( buf[0] == 'd' );
    99         cur          = &buf[1];
    100         str_expected = 1;
    101         tr_bencInit( val, ( is_dict ? TYPE_DICT : TYPE_LIST ) );
    102         while( cur - buf < len && cur[0] != 'e' )
    103         {
    104             if( makeroom( val, 1 ) ||
    105                 tr_bencLoad( cur, len - (cur - buf),
    106                              &val->val.l.vals[val->val.l.count], &p ) )
     65
     66        if( *buf=='i' ) /* Integer: i1234e */
     67        {
     68            int64_t num;
     69
     70            e = memchr( &buf[1], 'e', len - 1 );
     71            if( !e )
     72                return 1;
     73
     74            *e = '\0';
     75            num = strtoll( &buf[1], &p, 10 );
     76            *e = 'e';
     77
     78            if( p != e )
     79                return 1;
     80
     81            tr_bencInitInt( val, num );
     82            *end = p + 1;
     83            break;
     84        }
     85        else if( *buf=='l' || *buf=='d' )
     86        {
     87            /* List: l<item1><item2>e
     88               Dict: d<string1><item1><string2><item2>e
     89               A dictionary is just a special kind of list with an even
     90               count of items, and where even items are strings. */
     91            char * cur;
     92            char   is_dict;
     93            char   str_expected;
     94
     95            is_dict      = ( buf[0] == 'd' );
     96            cur          = &buf[1];
     97            str_expected = 1;
     98            tr_bencInit( val, ( is_dict ? TYPE_DICT : TYPE_LIST ) );
     99            while( cur - buf < len && cur[0] != 'e' )
     100            {
     101                if( makeroom( val, 1 ) ||
     102                    tr_bencLoad( cur, len - (cur - buf),
     103                                 &val->val.l.vals[val->val.l.count], &p ) )
     104                {
     105                    tr_bencFree( val );
     106                    return 1;
     107                }
     108                val->val.l.count++;
     109                if( is_dict && str_expected &&
     110                    val->val.l.vals[val->val.l.count - 1].type != TYPE_STR )
     111                {
     112                    tr_bencFree( val );
     113                    return 1;
     114                }
     115                str_expected = !str_expected;
     116
     117                cur = p;
     118            }
     119
     120            if( is_dict && ( val->val.l.count & 1 ) )
    107121            {
    108122                tr_bencFree( val );
    109123                return 1;
    110124            }
    111             val->val.l.count++;
    112             if( is_dict && str_expected &&
    113                 val->val.l.vals[val->val.l.count - 1].type != TYPE_STR )
    114             {
    115                 tr_bencFree( val );
    116                 return 1;
    117             }
    118             str_expected = !str_expected;
    119 
    120             cur = p;
    121         }
    122 
    123         if( is_dict && ( val->val.l.count & 1 ) )
    124         {
    125             tr_bencFree( val );
    126             return 1;
    127         }
    128 
    129         *end = cur + 1;
    130     }
    131     else
    132     {
    133         int    slen;
    134         char * sbuf;
    135 
    136         e = memchr( buf, ':', len );
    137         if( NULL == e )
    138         {
    139             return 1;
    140         }
    141 
    142         /* String: 12:whateverword */
    143         e[0] = '\0';
    144         slen = strtol( buf, &p, 10 );
    145         e[0] = ':';
    146 
    147         if( p != e || 0 > slen || len - ( ( p + 1 ) - buf ) < slen )
    148         {
    149             return 1;
    150         }
    151 
    152         sbuf = malloc( slen + 1 );
    153         if( NULL == sbuf )
    154         {
    155             return 1;
    156         }
    157 
    158         memcpy( sbuf, p + 1, slen );
    159         sbuf[slen] = '\0';
    160         tr_bencInitStr( val, sbuf, slen, 0 );
    161 
    162         *end = p + 1 + val->val.s.i;
     125
     126            *end = cur + 1;
     127            break;
     128        }
     129        else if( isdigit(*buf) )
     130        {
     131            int    slen;
     132            char * sbuf;
     133
     134            e = memchr( buf, ':', len );
     135            if( NULL == e )
     136            {
     137                return 1;
     138            }
     139
     140            /* String: 12:whateverword */
     141            e[0] = '\0';
     142            slen = strtol( buf, &p, 10 );
     143            e[0] = ':';
     144
     145            if( p != e || 0 > slen || len - ( ( p + 1 ) - buf ) < slen )
     146            {
     147                return 1;
     148            }
     149
     150            sbuf = malloc( slen + 1 );
     151            if( NULL == sbuf )
     152            {
     153                return 1;
     154            }
     155
     156            memcpy( sbuf, p + 1, slen );
     157            sbuf[slen] = '\0';
     158            tr_bencInitStr( val, sbuf, slen, 0 );
     159
     160            *end = p + 1 + val->val.s.i;
     161            break;
     162        }
     163        else /* invalid bencoded text... march past it */
     164        {
     165            ++buf;
     166            --len;
     167        }
    163168    }
    164169
Note: See TracChangeset for help on using the changeset viewer.