malloc and strcpy, illegall access, C



我读了很多关于这方面的文章,但找不到错误。

我有一个过程来说明是否在另一个较长的CSV字符串中找到了字符串值(在IP中下面的代码中是IPv4地址,allow_hosts应该是IPv4地址的CSV列表,但它应该适用于任何字符串和字符串的CSV列表)。

代码如下:

bool stringFound(char* inIP,char* allow_hosts){
bool found=false;
int i =0;
int j =0;
char* ip;
printf("strlen(allow_hosts)=%dn",strlen(allow_hosts));
while(i<strlen(allow_hosts) && !found){
    j=i;
    while(allow_hosts[i]!=',' && i<strlen(allow_hosts)){
        i++;
    }
    printf("jota = %dn",j);
    printf("i = %dn",i);
    printf("i-j+1 = %dn",i-j+1);
    ip = malloc(i-j+1);//1 more for ''
    strncpy(ip,allow_hosts+j,i);//line 25, illegal access, problem one
    printf("it copies=%sn",ip);
    ip[i-j]='';
    found = strcmp(ip,inIP)==0;
    //free(ip);//Problem two
    if(found)
        return found;
    i++;
}
return found;
};

当我测试它一次时,没有问题,结果是正确的,然而,当我在一行上运行它多次时,第三次或第四次会给我错误:

 malloc.c:2372: sysmalloc: Assertion 
 `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2]))
   - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) 
 || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof
 (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) 
 & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && 
 ((unsigned long) old_end & pagemask) == 0)' failed.
 Aborted (core dumped)

据我所知,这是malloc的一个问题,但当我用调用它时,我分配的内存数量是足够的

 stringFound("8.8.7.8","127.0.0.1,8.8.8.8");
 stringFound("8.8.54.8","127.0.0.1,8.8.8.8,192.168.92.3");

正在打印

 jota = 10
 i = 17
 i-j+1 = 8
 it copies=8.8.8.8
 strlen(allow_hosts)=30
 jota = 0
 i = 9
 i-j+1 = 10
 //the error I showed above appears here

我还用Valgrind测试了它,只是称之为Valgrind/myProgram,它说:

 ==3406== Invalid write of size 1
 ==3406==    at 0x402D763: strncpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
 ==3406==    by 0x80485EB: stringFound (esta.c:25)
 ==3406==    by 0x80486CC: test (esta.c:49)
 ==3406==    by 0x8048803: main (esta.c:75)
 ==3406==  Address 0x41fe0f0 is 0 bytes after a block of size 8 alloc'd

"test"是一个多次调用我的过程的函数,代码中第25行标记为"problem here"。

正如你所看到的,我在free()行有一条评论。如果我使用这条线,错误将变为

 Error in `./esta': free(): invalid next size (fast): 0x09d11008 
 Aborted (core dumped)

我认为两个错误都是由相同的原因引起的,但我没有发现错误

strncpy(ip,allow_hosts+j,i);//line 25, illegal access, problem one

是的,这应该是问题的根源。我认为第三个论点应该是i-j,而不是i

您应该写:

strncpy(ip,allow_hosts+j,i-j);

在循环的任何下一次迭代中,i都会变大,但您只为从j开始的ip字符串分配空间,因此您也必须只复制该部分。

strncpy(ip,allow_hosts+j,i);

这里的问题是,您需要一个片段的长度作为第三个参数,但您传递了结束位置。你应该通过i-j

2个问题:

ip = malloc(i-j+1);
// Wrong limit on strncpy
// strncpy(ip,allow_hosts+j,i);
strncpy(ip,allow_hosts+j,i-j);
// ip may not be null character terminated,  re-arrange code
ip[i-j]='';
printf("it copies=%sn",ip);
// ip[i-j]='';

free()问题很可能是由于上述问题的损坏。


更微妙的问题是:strlen返回的长度类型是size_t。如果size_tint的大小相似,则此问题可能不会轻易显现出来最好不要指望这一点,使用CCD_ 10。

size_t i =0;
size_t j =0;
// Change format specifier too.
printf("strlen(allow_hosts)=%zun",strlen(allow_hosts));
printf("jota = %zu",j);  // Review all printf formats
  • strstr()是一个可用的库函数
  • 你不需要malloc;只要检查一下字符串
  • 如果找到该字符串,则该字符串可以是较大的有效带点四元字符串的部分
  • (注意:strncpy()是一个糟糕的函数,非常需要)

#include <stdio.h>
#include <string.h>
int stringFound(char *inIP, char *allow_hosts){
char *cp;
cp = strstr(allow_hosts, inIP);
        /* IF substring is found:
        ** check if it is PART of a LARGER dotted quad string
        */
if (!cp) return 0;
if (cp > allow_hosts && cp[-1] >= '0' && cp[-1] <= '9' ) return 0;
cp += strlen(inIP); if (*cp >= '0' && *cp <= '9' ) return 0;
return 1;
}
int main(int argc, char **argv)
{
int found;
char *the_ip = "1.2.3.4";
char *should_fail = "5.2.3.4 ,1.2.3.45, 11.2.3.4, 1.2.3.4.";
char *should_match = "5.2.3.4 ,6.2.3.4,  1.2.3.4, 9.2.3.4";
found = stringFound(the_ip, should_fail);
printf("(should fail) Found=%dn" , found);
found = stringFound(the_ip, should_match);
printf("(should match) Found=%dn" , found);
return 0;
}

最新更新