memcpy上的分段错误

时间:2013-03-19 08:36:05

标签: c segmentation-fault memcpy

完整的代码在

http://docs.google.com/file/d/0B09y_TWqTtwlaHNjdjYybHVIcjA/edit?usp=sharing

    char data[]="just for a try";
    u_char *packet=(u_char *)malloc(28+sizeof(data));
     ...
     ...


    u_char *udp_data=(u_char *)malloc(8+sizeof(data));
    if(udp_data == NULL )
            perror("allocating space for udp_data fails\n");
    memcpy(udp_data, &udp, sizeof(udp));
    memcpy(udp_data+8, data, sizeof(data));
    udp.check = in_cksum_udp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)udp_data, sizeof(udp)+sizeof(data)); // if I comment this line, no segmentation fault!
    free(udp_data);
    udp_data=NULL;

    // I get segmentation fault on the next line:
    memcpy(packet + 20, &udp, sizeof(udp));

问题是cksum_udp()函数 错误是

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a2b in run (arg=0x0) at raw_udp_client.c:115
115     memcpy(packet + 20, &udp, sizeof(udp));

核心转储 https://docs.google.com/file/d/0B09y_TWqTtwldFI5UGdfc01RU28/edit?usp=sharing 在in_cksum_udp()

之前
ip = {ip_hl = 5, ip_v = 4, ip_tos = 0 '\000', ip_len = 10752, ip_id = 0, 
ip_off = 0, ip_ttl = 64 '@', ip_p = 17 '\021', ip_sum = 32808, ip_src = {
s_addr = 1825136778}, ip_dst = {s_addr = 376725642}}
udp = {source = 51377, dest = 125, len = 5632, check = 0}
sd = 0
on = 1
sin = {sin_family = 1, sin_port = 0, sin_addr = {s_addr = 0}, 
sin_zero = "ݲ\360\000\000\000\000"}
packet = 0x602010 "E"
data = "I'm not here!"
udp_data = 0x602050 "\261\310}"
<_>在in_cksum_udp()之后

ip = {ip_hl = 0, ip_v = 0, ip_tos = 0 '\000', ip_len = 0, ip_id = 0, 
ip_off = 0, ip_ttl = 0 '\000', ip_p = 0 '\000', ip_sum = 0, ip_src = {
  s_addr = 0}, ip_dst = {s_addr = 0}}
udp = {source = 0, dest = 0, len = 0, check = 4842}
sd = 0
on = 0
sin = {sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, 
sin_zero = "\000\000\000\000\000\000\000"}
packet = 0x0
data = '\000' <repeats 13 times>
udp_data = 0x0

in_cksum_udp()函数如下,我没有看到任何问题:

struct psd_udp {
    struct in_addr src;
    struct in_addr dst;
    unsigned char pad;
    unsigned char proto;
    unsigned short udp_len;
    struct udphdr udp;
};

unsigned short in_cksum(unsigned short *addr, int len)
{
    int nleft = len;
    int sum = 0;
    unsigned short *w = addr;
    unsigned short answer = 0;

    while (nleft > 1) {
            sum += *w++;
            nleft -= 2;
    }

    if (nleft == 1) {
            *(unsigned char *) (&answer) = *(unsigned char *) w;
            sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    answer = ~sum;
    return (answer);
}


unsigned short in_cksum_udp(int src, int dst, unsigned short *addr, int len)
{
    struct psd_udp buf;

    memset(&buf, 0, sizeof(buf));
    buf.src.s_addr = src;
    buf.dst.s_addr = dst;
    buf.pad = 0;
    buf.proto = IPPROTO_UDP;
    buf.udp_len = htons(len);
    memcpy(&(buf.udp), addr, len);
    return in_cksum((unsigned short *)&buf, 12 + len);
}

似乎该函数与指针包指向的内存无关 什么是潜在的问题?

2 个答案:

答案 0 :(得分:11)

在功能in_csum_udp中,此行:

memcpy(&(buf.udp), addr, len);

正在将sizeof(struct udphdr) + sizeof(data)字节复制到buf.udp,即struct udphdr。由于这是结构的最后一个元素,因此堆栈会被破坏。

答案 1 :(得分:0)

这是另一个错误(读取外部缓冲区)。这可能不是导致内存损坏的原因。

您要将len个字节发送到in_cksumin_cksum认为它有len short s。