diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d7bd65be9d..82c44d6df6 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,23 @@ The license applies to all entries newer than 2009-04-28. */ +2011-02-11 14:46 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/src/rtl/base64d.c + ! fixed destination buffer size calculation - it was too small + ! fixed to work with platform/compilers where 'char' is unsigned type. + Please NEVER use 'char' type in math calculation without explicit + 'signed' or 'unsigned' specifier. On some platforms (i,e. MIPS Linux + ports or in all OpenWatcom builds) 'char' is unsigned type. I once + cleaned whole code and fixed all wrong places. I do not want to + repeat it - sometimes is hard to locate problematic places. + ! fixed index to ASCII decode table verification - '{' was accepted + as valid base64 char. + BTW this code works only on ASCII based machines. It's not the + one code with such limitation in Harbour SVN anyhow it would be + good to mark such limitation - maybe someone will want to port + Harbour to some IBM mainframe machines. + % removed redundant code + 2011-02-11 13:30 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) * src/rtl/base64d.c ! Fixed crash when empty or non-string parameter was passed to HB_BASE64DECODE(). diff --git a/harbour/src/rtl/base64d.c b/harbour/src/rtl/base64d.c index 1cd2dce911..6ce96e2027 100644 --- a/harbour/src/rtl/base64d.c +++ b/harbour/src/rtl/base64d.c @@ -55,20 +55,11 @@ #include "hbapi.h" -typedef enum -{ - step_a, step_b, step_c, step_d -} base64_decodestep; +/* Warning: this code works only on ASCII based machines */ -typedef struct +static signed char base64_decode_value( char value_in ) { - base64_decodestep step; - char plainchar; -} base64_decodestate; - -static int base64_decode_value( char value_in ) -{ - static const char s_decoding[] = + static const signed char s_decoding[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, @@ -77,88 +68,59 @@ static int base64_decode_value( char value_in ) }; value_in -= 43; - if( value_in < 0 || value_in > ( char ) HB_SIZEOFARRAY( s_decoding ) ) + if( value_in < 0 || value_in >= ( char ) HB_SIZEOFARRAY( s_decoding ) ) return -1; return s_decoding[ ( int ) value_in ]; } -static int base64_decode_block( const char * code_in, const int length_in, char * pszPlainttextOut ) +static HB_SIZE base64_decode_block( const char * code_in, const HB_SIZE length_in, char * pszPlainttextOut ) { - base64_decodestep step; - char plainchar; - const char * codechar = code_in; + const char * code_end = code_in + length_in; char * pszPlainchar = pszPlainttextOut; - char fragment; + signed char fragment; - step = step_a; - plainchar = 0; - - *pszPlainchar = plainchar; - - switch( step ) + for( ;; ) { - for( ;; ) + do { - case step_a: - do - { - if( codechar == code_in + length_in ) - { - step = step_a; - plainchar = *pszPlainchar; - return pszPlainchar - pszPlainttextOut; - } - fragment = ( char ) base64_decode_value( *codechar++ ); - } - while( fragment < 0 ); - *pszPlainchar = ( fragment & 0x03f ) << 2; - case step_b: - do - { - if( codechar == code_in + length_in ) - { - step = step_b; - plainchar = *pszPlainchar; - return pszPlainchar - pszPlainttextOut; - } - fragment = ( char ) base64_decode_value( *codechar++ ); - } - while( fragment < 0 ); - *pszPlainchar++ |= ( fragment & 0x030 ) >> 4; - *pszPlainchar = ( fragment & 0x00f ) << 4; - case step_c: - do - { - if( codechar == code_in + length_in ) - { - step = step_c; - plainchar = *pszPlainchar; - return pszPlainchar - pszPlainttextOut; - } - fragment = ( char ) base64_decode_value( *codechar++ ); - } - while( fragment < 0 ); - *pszPlainchar++ |= ( fragment & 0x03c ) >> 2; - *pszPlainchar = ( fragment & 0x003 ) << 6; - case step_d: - do - { - if( codechar == code_in + length_in ) - { - step = step_d; - plainchar = *pszPlainchar; - return pszPlainchar - pszPlainttextOut; - } - fragment = ( char ) base64_decode_value( *codechar++ ); - } - while( fragment < 0 ); - *pszPlainchar++ |= ( fragment & 0x03f ); + if( codechar == code_end ) + return pszPlainchar - pszPlainttextOut; + fragment = base64_decode_value( *codechar++ ); } + while( fragment < 0 ); + *pszPlainchar = ( fragment & 0x03f ) << 2; + + do + { + if( codechar == code_end ) + return pszPlainchar - pszPlainttextOut; + fragment = base64_decode_value( *codechar++ ); + } + while( fragment < 0 ); + *pszPlainchar++ |= ( fragment & 0x030 ) >> 4; + *pszPlainchar = ( fragment & 0x00f ) << 4; + + do + { + if( codechar == code_end ) + return pszPlainchar - pszPlainttextOut; + fragment = base64_decode_value( *codechar++ ); + } + while( fragment < 0 ); + *pszPlainchar++ |= ( fragment & 0x03c ) >> 2; + *pszPlainchar = ( fragment & 0x003 ) << 6; + + do + { + if( codechar == code_end ) + return pszPlainchar - pszPlainttextOut; + fragment = base64_decode_value( *codechar++ ); + } + while( fragment < 0 ); + *pszPlainchar++ |= ( fragment & 0x03f ); } - /* control should not reach here */ - return pszPlainchar - pszPlainttextOut; } HB_FUNC( HB_BASE64DECODE ) @@ -167,7 +129,7 @@ HB_FUNC( HB_BASE64DECODE ) if( len > 0 && len <= INT_MAX ) /* TOFIX */ { - char * code = ( char * ) hb_xgrab( ( ( ( ( len - 1 ) * 3 ) / 4 ) + 1 ) * sizeof( char ) ); + char * code = ( char * ) hb_xgrab( ( ( ( len * 3 ) / 4 ) + 1 ) * sizeof( char ) ); HB_SIZE nSize = base64_decode_block( hb_parcx( 1 ), len, code ); hb_retclen_buffer( code, nSize );