ReneNyffenegger / cpp-base64

base64 encoding and decoding with c++
Other
891 stars 311 forks source link

Decoding throws const char* exception: If input is correct, this line should never be reached. #13

Closed kosniaz closed 4 years ago

kosniaz commented 4 years ago

Hello,

First of all, thanks for the implementation. I'd like to report a small bug. In some cases of URL-safe base64 strings, the decoding fails, because the exception If input is correct, this line should never be reached. is thrown.

If you want to check the code directly, it's pretty straightforward. Inside base64_decode(), in the main loop, there is a missing condition in the last if, which checks the last of character in the current quartet, namely the pos+3-th.

    while (pos < in_len) {

       unsigned int pos_of_char_1 = pos_of_char(encoded_string[pos+1] );

       ret.push_back( ( (pos_of_char(encoded_string[pos+0]) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4));

       if (encoded_string[pos+2] != '=' && encoded_string[pos+2] != '.') { // accept URL-safe base 64 strings, too, so check for '.' also.

          unsigned int pos_of_char_2 = pos_of_char(encoded_string[pos+2] );
          ret.push_back( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2));

          if (encoded_string[pos+3] != '=') {
             ret.push_back( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string[pos+3])   );
          }
       }

       pos += 4;
    }

I believe that the same check done for the pos+2-th char should be done for the pos+3-th char

How to reproduce:

Just create a bytestring with length= 3k-1, encode it as URL-safe and decode it.

void reproduce_error() {
    //generate any sequence of bytes which needs exactly one char for padding.
    unsigned char my_bytes[17];
    int i;
    for (i=0; i<17;i++) {
        char random_char = 'a';
        my_bytes[i] = *(reinterpret_cast <unsigned char const*> (&random_char));
    }
    std::string s =base64_encode(my_bytes,17,true); 
    base64_decode(s);
}
ReneNyffenegger commented 4 years ago

Thanks for the notification. You're absolutely correct. I have fixed the issue.