jiych.guru jiych.guru - 1 month ago 8
C Question

K&R:C - Stack smashing detected

My code is like this:

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
like this:

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


When I use
gcc -Wall -O2 -g a.c -o a.out
, and execute
a.out -x -n 111<find_test
, where
find_test
is just my test data:

line1:111111111111111
line2:222222222222222
line3:222222222222222
line4:444444444444444
line2:kasdskskdk


I got the error message:

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


but if I use
gcc -Wall -O2 -g -fno-stack-protector a.c -o a.out
and execute
a.out -x -n 111<find_test
everything is ok. I could't find the reason. Can anyone help?

Answer

You seem to have mixed up MAX_LINES and MAX_LENGTH. Looks like you allocate space for the former, but what you read in is the latter.

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

    ....

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

BTW, why don't you use fgets() instead of getline()?

Update

but,if i use gcc -Wall -O2 -g -fno-stack-protector a.c -o a.out,and execute a.out -x -n 111 < find_test, everything is ok

No. Most definitely everything is not OK. You are still overwriting a memory area; the overwrite may be "mostly harmless" now and on this specific platform, but it is still potentially lethal. In another context, the same error, unless some protection were in place (luckily, nowadays it very often is -- but you can't count on luck!) might allow a remote attacker to gain control of your machine. If you were to try with longer lines, chances are that your "OK" program with no stack protector would segfault again (or, for more complex programs, return incorrect results or even cause damage to the system).