K&R:C - 检测到堆栈粉碎

jiy*_*uru 3 c stack-corruption

我的代码是这样的:

int find_test(int argc, char *argv[])
{
    char line[MAX_LINES];
    int c, except = 0, found = 0, number = 0;
    long lineno = 0;
    int i = 0;

    while(--argc > 0 && (*++argv)[0] == '-'){
        while(c = *++argv[0]){
            switch(c){
                case 'x':
                    except = 1;
                    break;
                case 'n':
                    number = 1;
                    break;
                default:
                    printf("find:illegal option %c\n", c);
                    argc = 0;
                    found = -1;
                    break;
            }
        }
    }
    if(argc != 1){
        printf("Usage:find -x -n pattern\n");
    }else{
        while(getline(line, MAX_LENGTH) > 0){
            lineno++;
            if((strstr(line, *argv) != NULL) != except){
                if(number)
                    printf("%ld:", lineno);
                printf("%s\n", line);
                found++;
            }
        }
    }
    return found;
}
Run Code Online (Sandbox Code Playgroud)

getline 像这样:

int getline(char *line, int maxline)
{
    char *p = line;
    int c;

    while(maxline-- && (c = getchar()) != EOF && c != '\n'){
        *line++ = c;
    }
    if(maxline > 0)
        *line = '\0';

    return line - p;
}
Run Code Online (Sandbox Code Playgroud)

当我使用gcc -Wall -O2 -g a.c -o a.out和执行时a.out -x -n 111<find_test,find_test我的测试数据只在哪里:

line1:111111111111111
line2:222222222222222
line3:222222222222222
line4:444444444444444
line2:kasdskskdk
Run Code Online (Sandbox Code Playgroud)

我收到了错误消息:

*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7ead138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7ead0f0]
./a.out[0x8048e95]
./a.out[0x8048ec2]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7dd6450]
./a.out[0x8048641]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:08 17488      /home/jyc/prgm/the_c_p_l/a.out
0804a000-0804b000 rw-p 00001000 08:08 17488      /home/jyc/prgm/the_c_p_l/a.out
0804b000-0806c000 rw-p 0804b000 00:00 0          [heap]
b7dbf000-b7dc0000 rw-p b7dbf000 00:00 0 
b7dc0000-b7f09000 r-xp 00000000 08:08 694644     /lib/tls/i686/cmov/libc-2.7.so
b7f09000-b7f0a000 r--p 00149000 08:08 694644     /lib/tls/i686/cmov/libc-2.7.so
b7f0a000-b7f0c000 rw-p 0014a000 08:08 694644     /lib/tls/i686/cmov/libc-2.7.so
b7f0c000-b7f0f000 rw-p b7f0c000 00:00 0 
b7f0f000-b7f32000 r-xp 00000000 08:08 694648     /lib/tls/i686/cmov/libm-2.7.so
b7f32000-b7f34000 rw-p 00023000 08:08 694648     /lib/tls/i686/cmov/libm-2.7.so
b7f3a000-b7f44000 r-xp 00000000 08:08 677855     /lib/libgcc_s.so.1
b7f44000-b7f45000 rw-p 0000a000 08:08 677855     /lib/libgcc_s.so.1
b7f45000-b7f49000 rw-p b7f45000 00:00 0 
b7f49000-b7f4a000 r-xp b7f49000 00:00 0          [vdso]
b7f4a000-b7f64000 r-xp 00000000 08:08 678556     /lib/ld-2.7.so
b7f64000-b7f66000 rw-p 00019000 08:08 678556     /lib/ld-2.7.so
bfa26000-bfa3b000 rw-p bffeb000 00:00 0          [stack]
Run Code Online (Sandbox Code Playgroud)

但如果我使用gcc -Wall -O2 -g -fno-stack-protector a.c -o a.out并执行a.out -x -n 111<find_test一切都没问题.我找不到原因.有人可以帮忙吗?

LSe*_*rni 6

你似乎混淆了MAX_LINESMAX_LENGTH.看起来你为前者分配空间,但你读到的是后者.

int find_test(int argc, char *argv[])
{
    char line[MAX_LINES];            <-------------
    int c...

    ....

    while(getline(line, MAX_LENGTH) > 0){  <-------
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你为什么不用fgets()而不是getline()

更新

但是,如果我使用gcc -Wall -O2 -g -fno-stack-protector ac -o a.out,并执行a.out -x -n 111 <find_test,一切都还可以

不,绝对一切都不行.你还在覆盖一个记忆区域; 现在和在这个特定的平台上,覆盖可能"几乎无害" ,但它仍然可能是致命的.在另一个上下文中,同样的错误,除非有一些保护措施(幸运的是,现在经常是 - 但你不能指望运气!)可能允许远程攻击者控制你的机器.如果您尝试使用更长的线路,那么没有堆栈保护器的"OK"程序可能会再次发生段错误(或者,对于更复杂的程序,返回不正确的结果甚至会导致系统损坏).