Вопрос

Ну, я беру пакеты прямо из сети и извлекаю из них TCP-потоки.

Короче говоря, это означает удаление различных заголовков (например, данных eth->IP->TCP->stream).

В функции, которая вызывается, когда я наконец просмотрел все заголовки, возникает странная ошибка.

    /*Meta is a pointer to the IP header, pkt is a pointer to the TCP header*/
    virtual const u_char* processPacket(const u_char* pkt, const u_char* meta) {
        //Extract IP info from meta.
        iphdr* metaHdr = (iphdr*)meta;
        //Form TCP header from the current offset, hdr.
        const tcphdr* hdr = (const tcphdr*)pkt;

        //Do pointer math to figure out the size of the stream data.
        u_int32_t len = ntohs(metaHdr->tot_len) - metaHdr->ihl*4 - hdr->doff*4;
        if(len > 0)
        {
            //Store TCP stream data in a queue, mapped to it's IP source.
            TCPStream* stream = new TCPStream();
            stream->seqNumber = ntohl(hdr->seq);
            stream->streamData = new u_char(len);
            //memcpy(stream->streamData, offset(pkt), len);
            for(u_int32_t i = 0; i < len; i++)
            {
                printf("k%i-%i",len, i); //Used to figure out when the segfault occurs.
                stream->streamData[i] = offset(pkt)[i]; //Offset returns a pointer to the data under the TCP header
            }

            //streams[metaHdr->saddr].push(stream);
        }

        return offset(pkt);
    };

TCP-поток — это просто u_int32_t и u_char* указывая на копию данных пакета.Итак, когда я использовал memcpy, произошел сбой.
Очевидно, либо мои указатели были неверными, либо я испортил длину.

В данном конкретном случае длина данных составляет 1380 байт (подтверждено Wireshark), поэтому len вычисляется правильно.

Хорошо, значит, у меня, должно быть, перепутаны указатели (но не NULL).Я провел следующий эксперимент:

stream->streamData[0] = offset(pkt)[0]; //Works
stream->streamData[0] = offset(pkt)[len]; //Works, odd.
stream->streamData[len] = offset(pkt)[0]; //Fails, scary
stream->streamData[len] = offset(pkt)[len]; //Fails

Итак, я совершаю ошибку при слишком глубоком разыменовании в потоке данных (точнее, индексе 1236)!Но экземплярstreamData создается как:

stream->streamData = new u_char(len); 

Я начинаю перебор потоковых данных с i=0, поэтому не пропускаю кучу данных.потоковые данные u_char* и offset(pkt) является u_char* так что я не путаю свои типы.

Это терпит неудачу в конкретном пакете после успешной итерации через более чем 3000 других пакетов.Размер файла дампа составляет 27 МБ, а у меня 4 гигабайта оперативной памяти, так что я не думаю, что у меня заканчивается или что-то в этом роде...Итак, я вынужден сделать вывод, что new не выделяет достаточно памяти, но почему?

Это было полезно?

Решение

stream->streamData = new u_char(len);

При этом выделяется один символ, инициализированный для len.

Чтобы выделить массив, используйте:

stream->streamData = new u_char[len];

И где бы вы его ни освободили:

delete [] stream->streamData;

Редактировать:

stream->streamData[len] = offset(pkt)[0]; //Fails, scary

Это было бы неопределенное поведение, даже если бы массив был выделен правильно.Допустимые индексы для доступа: от 0 до len не инклюзивно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top