3

我的代码是这样的:

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;
}

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;
}

当我使用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

我收到错误消息:

*** 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]

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

4

2 回答 2

5

你好像搞混MAX_LINESMAX_LENGTH。看起来您为前者分配了空间,但您读入的是后者。

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

    ....

    while(getline(line, MAX_LENGTH) > 0){  <-------

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

更新

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

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

于 2012-11-15T16:14:16.000 回答
2

当您到达MAX_LENGTH您的行时,您strstr可以扫描超出缓冲区,因为缓冲区没有 '\0' 字符。

编辑:还有一点我想说。那是有争议的,因为这两种可能性都有争论。unsigned在我看来,使用缓冲区索引会更好。这将迫使以不同的方式处理循环,这更容易纠正。此外,当使用 索引数组时unsigned,如果发生下溢,您将更有可能segmentation fault使用它而不是使用有符号积分。我们最近在我们的项目中遇到了这种情况(自 1998 年以来一直在生产的系统),我将代码中的一个变量更改为 asize_t并捕获了 2 个从一开始就被遗漏的下溢错误。

EDIT2:我想提出的另一个文体观点。避免循环表达式中的后(in|de)crement,它们通常会导致细微的错误(如上面的错误)。预(减少|减少)减少不是问题。post-(in|de)crement 有问题的原因是,当您在心理上解析表达式的条件(继续或中断)时,它立即无效,即在表达式的末尾,您在脑海中使用的值看到结果已经不存在了。也许只有我一个人,但是在我用 C 编程的 25 年中,有很多次我在循环中得到了后(in|de)增量错误,并且总是通过前(in|de)增量来纠正或从布尔表达式中取出增量。

于 2012-11-15T16:20:48.763 回答