Changeset 7656


Ignore:
Timestamp:
Jan 10, 2009, 10:48:58 PM (12 years ago)
Author:
charles
Message:

(trunk libT) #1675: better utf8 validation of metainfo name, creator, and comment fields

Location:
trunk/libtransmission
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/ConvertUTF.c

    r7654 r7656  
    4040------------------------------------------------------------------------ */
    4141
    42 
     42#ifdef CVTUTF_DEBUG
     43 #include <stdio.h>
     44#endif
     45#include <string.h> /* strlen() */
     46#include <unistd.h> /* ssize_t */
    4347#include "ConvertUTF.h"
    44 #ifdef CVTUTF_DEBUG
    45 #include <stdio.h>
    46 #endif
    4748
    4849static const int halfShift  = 10; /* used for shifting by 10 bits */
     
    346347}
    347348
     349/**
     350 * This is a variation of isLegalUTF8Sequence() that behaves like g_utf8_validate().
     351 * In addition to knowing if the sequence is legal, it also tells you the last good character.
     352 */
     353Boolean
     354tr_utf8_validate( const char * str, ssize_t max_len, const char ** end )
     355{
     356    const UTF8* source = (const UTF8*) str;
     357    const UTF8* sourceEnd = source;
     358
     359    if( max_len == 0 )
     360        return true;
     361
     362    if( str == NULL )
     363        return false;
     364
     365    sourceEnd = source + ((max_len < 0) ? strlen(str) : (size_t)max_len);
     366
     367    if( source == sourceEnd )
     368    {
     369        if( end != NULL )
     370            *end = (const char*) source;
     371        return true;
     372    }
     373
     374    for( ;; )
     375    {
     376        const int length = trailingBytesForUTF8[*source] + 1;
     377        if (source + length > sourceEnd) {
     378            if( end != NULL )
     379                *end = (const char*) source;
     380            return false;
     381        }
     382        if (!isLegalUTF8(source, length)) {
     383            if( end != NULL )
     384                *end = (const char*) source;
     385            return false;
     386        }
     387        source += length;
     388        if (source >= sourceEnd) {
     389            if( end != NULL )
     390                *end = (const char*) source;
     391            return true;
     392        }
     393    }
     394
     395   
     396}
     397
     398
    348399/* --------------------------------------------------------------------- */
    349400
  • trunk/libtransmission/ConvertUTF.h

    r7654 r7656  
    55#error only libtransmission should #include this header.
    66#endif
     7
     8#include <unistd.h> /* ssize_t */
    79
    810/*
     
    150152Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
    151153
     154
     155/* intended to work the same as g_utf8_validate */
     156Boolean tr_utf8_validate( const char * str, ssize_t max_len, const char ** end );
     157
     158
    152159#ifdef __cplusplus
    153160}
  • trunk/libtransmission/metainfo.c

    r7598 r7656  
    125125
    126126static int
    127 getfile( char **      setme,
    128          const char * root,
    129          tr_benc *    path )
     127getfile( char        ** setme,
     128         const char   * root,
     129         tr_benc      * path )
    130130{
    131131    int err;
     
    357357    tr_benc *       beInfo;
    358358    tr_benc *       meta = (tr_benc *) meta_in;
     359    tr_bool         err;
    359360
    360361    /* info_hash: urlencoded 20-byte SHA1 hash of the value of the info key
     
    379380        return "name";
    380381    tr_free( inf->name );
    381     inf->name = tr_strdup( str );
     382    inf->name = tr_utf8clean( str, -1, &err );
    382383
    383384    /* comment */
     
    386387            str = "";
    387388    tr_free( inf->comment );
    388     inf->comment = tr_strdup( str );
     389    inf->comment = tr_utf8clean( str, -1, &err );
    389390
    390391    /* created by */
     
    393394            str = "";
    394395    tr_free( inf->creator );
    395     inf->creator = tr_strdup( str );
     396    inf->creator = tr_utf8clean( str, -1, &err );
    396397
    397398    /* creation date */
  • trunk/libtransmission/utils-test.c

    r6993 r7656  
    22#include <string.h> /* strcmp */
    33#include "transmission.h"
     4#include <unistd.h> /* ssize_t */
     5#include "ConvertUTF.h" /* tr_utf8_validate*/
    46#include "platform.h"
    57#include "utils.h"
     
    136138}
    137139
     140static int
     141test_utf8( void )
     142{
     143    const char * in;
     144    char * out;
     145    tr_bool err;
     146
     147    in = "hello world";
     148    out = tr_utf8clean( in, -1, &err );
     149    check( err == FALSE )
     150    check( out != NULL )
     151    check( !strcmp( out, in ) )
     152    tr_free( out );
     153
     154    in = "hello world";
     155    out = tr_utf8clean( in, 5, &err );
     156    check( err == FALSE )
     157    check( out != NULL )
     158    check( !strcmp( out, "hello" ) )
     159    tr_free( out );
     160
     161    /* this version is not utf-8 */
     162    in = "Òðóäíî áûòü Áîãîì";
     163    out = tr_utf8clean( in, 17, &err );
     164    check( out != NULL )
     165    check( err != 0 )
     166    check( strlen( out ) == 17 )
     167    check( tr_utf8_validate( out, -1, NULL ) )
     168    tr_free( out );
     169
     170    /* same string, but utf-8 clean */
     171    in = "ÒðóÀíî áûòÌ Áîãîì";
     172    out = tr_utf8clean( in, -1, &err );
     173    check( out != NULL )
     174    check( !err );
     175    check( tr_utf8_validate( out, -1, NULL ) )
     176    check ( !strcmp( in, out ) )
     177    tr_free( out );
     178
     179    return 0;
     180}
     181
    138182int
    139183main( void )
     
    161205    if( ( i = test_buildpath( ) ) )
    162206        return i;
     207    if( ( i = test_utf8( ) ) )
     208        return i;
    163209
    164210    /* test that tr_cryptoRandInt() stays in-bounds */
  • trunk/libtransmission/utils.c

    r7632 r7656  
    3333
    3434#include "transmission.h"
     35#include "ConvertUTF.h"
    3536#include "list.h"
    3637#include "utils.h"
     
    13201321    return first;
    13211322}
     1323
     1324/***
     1325****
     1326***/
     1327
     1328char*
     1329tr_utf8clean( const char * str, ssize_t max_len, tr_bool * err )
     1330{
     1331    const char zero = '\0';
     1332    char * ret;
     1333    struct evbuffer * buf = evbuffer_new( );
     1334    const char * end;
     1335
     1336    if( err != NULL )
     1337        *err = FALSE;
     1338
     1339    if( max_len < 0 )
     1340        max_len = (ssize_t) strlen( str );
     1341
     1342    while( !tr_utf8_validate ( str, max_len, &end ) )
     1343    {
     1344        const ssize_t good_len = end - str;
     1345
     1346        evbuffer_add( buf, str, good_len );
     1347        max_len -= ( good_len + 1 );
     1348        str += ( good_len + 1 );
     1349        evbuffer_add( buf, "?", 1 );
     1350
     1351        if( err != NULL )
     1352            *err = TRUE;
     1353    }
     1354
     1355    evbuffer_add( buf, str, max_len );
     1356    evbuffer_add( buf, &zero, 1 );
     1357    ret = tr_memdup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) );
     1358    assert( tr_utf8_validate( ret, -1, NULL ) );
     1359    evbuffer_free( buf );
     1360    return ret;
     1361}
  • trunk/libtransmission/utils.h

    r7641 r7656  
    238238void           tr_wait( uint64_t delay_milliseconds );
    239239
     240char*          tr_utf8clean( const char  * str,
     241                             ssize_t       max_len,
     242                             tr_bool     * err );
     243
     244
    240245/***
    241246****
Note: See TracChangeset for help on using the changeset viewer.