1. C++ / Говнокод #4473

    +163

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    LPBYTE OUTBUFF = NULL;
    	DWORD BUFFSIZE = 0;
    ...
    		int pgp_res = m_pgp.EncodeBuff2Buff(
    			( LPCVOID ) ( LPCTSTR ) post_data.c_str(),
    			( DWORD ) post_data.length(),
    			OUTBUFF,
    			BUFFSIZE,
    			( LPCTSTR ) query_mts_cfg().query_crypto_public_key().c_str() ); 
    ...
    			std::string s;
    			// мы будем рассматривать буфер как строку, а PGPEncode
    			// естественно не ограничивает буфер нулевым
    			// символом, поэтому строку из буфера надо
    			// ограничивать насильно
    			s = std::string( ( char* ) OUTBUFF );
    			s = s.substr( 0, BUFFSIZE );

    1) Проблема проявилась после 5 лет боевой эксплуатации.
    2) Все загодногожено было именно так. Т.е. автор понимал \0, сделал что-то, но все равно с ошибкой.

    Запостил: bsivko, 28 Октября 2010

    Комментарии (11) RSS

    • Вот это ужас... А всего-то нужно было использовать конструктор std::string ( const char * s, size_t n );
      Ответить
    • И это работало 5 лет?
      Ответить
      • Да. При чем на трех разных машинах и в нескольких экземплярах в режиме 24х7.
        Ответить
    • >Проблема проявилась после 5 лет боевой эксплуатации.
      Первый раз за 5 лет появился 0 в данных ?
      Ответить
      • Либо вышли за пределы памяти, из которой можно читать...
        Ответить
      • Данные всегда base64.
        Выход за пределы памяти произошел впервые в 16-й строке.
        Ответить
        • Пардон, а за какие пределы можно выйти в 16й строке ?
          Ответить
          • Строка, которая хранится по адресу OUTBUFF, имеет размер BUFFSIZE, но не оканчивается нулем гарантированно (то, что было сформировано до 16-й строки).

            При отработке конструктора (в 16-й строке) формируется C-шная строка, которая захватывает массив в BUFFSIZE и все остальное до тех пор, пока не встретит за OUTBUFF+BUFFSIZE нулевой код.

            Программа ломается тогда, когда между OUTBUFF+BUFFSIZE и нулевым кодом окончания строки "заканчивается память" (на деле это undefined behavior).
            Ответить
            • Т.е. превысило std::string::max_size() ?
              Ответить
              • Это вряд ли.

                В конструктор передается указатель char * на строку, которая не строка, а потенциальный хлам. В результате при формировании строки конструктор читает память до тех пор, пока не встретит 0. И если в этом процессе происходит попытка доступа к памяти, которой нет либо нет доступа, то получаем undefined behavior.

                Например вот эта программа у меня ломается:

                #include <iostream>

                int main ()
                {
                const unsigned int c_size = 100;
                char * str = new char[c_size];
                for( unsigned int i = 0; i < c_size; ++i )
                str[i] = ' ';

                for( unsigned int i = 0; i < c_size*2000; ++i )
                std::cout << (int)str[i] << " ";

                return 0;
                }
                Ответить

    Добавить комментарий