Buffer overflow detected in a program that runs flawlessly ( apparently)

徘徊边缘 提交于 2019-12-10 10:59:44

问题


On a string containing as, bs and cs, we can perform the following operation. We can take any two adjacent different characters and replace them by the third. For example, 'ab' gets reduced to 'c' and so does 'ba' and so on. I wrote this code to perform the following operation on t strings (t<=100) and max length of strings = 100

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int redlen(char string[100][100], int x)
{
    int g, checker; checker = 1;
    for(; checker; )
    {
    checker = 0;
    for(int i = 0;string[x][i]!='\0'; i++)
    {
        if((string[x][i]=='a' && string[x][i+1]=='b') || (string[x][i]=='b' && string[x][i+1]=='a'))
        {
            string[x][i]='c';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;  
        }   
        else if((string[x][i]=='b' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='b'))
        {
            string[x][i]='a';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;
        }
        else if((string[x][i]=='a' && string[x][i+1]=='c') || (string[x][i]=='c' && string[x][i+1]=='a'))
        {
            string[x][i]='b';
            checker = 1;
            for(g = i+1; string[x][g]!='\0'; g++)
            {
                string[x][g]=string[x][g+1];
            }
            i = 0;          
        }   
    }   
}
return strlen(string[x]);
}           

void main()
{
    int t; char r[3];
    gets(r);
    t = atoi(r);
    char string[100][100];
    int i;
    for(i = 0; i<t; i++)
    {
        gets(string[i]);
    }
    int printval;
    for(i = 0; i<t; i++)
    {
            printval = redlen(string, i);
            printf("%d",printval);
            printf(" \n");
    }
}

It worked fine on the sample case of the problem and also on the cases I developed on my own. But when I submitted it online, it passed only one of the ten cases, and in the rest, this message popped up.

 *** buffer overflow detected ***: /run-DkQcMiKXhWz9LjirrRnu/solution terminated
======= Backtrace: =========
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__fortify_fail+0x45)[0xb76df045]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(+0x102e1a)[0xb76dde1a]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__gets_chk+0x165)[0xb76ddd85]
/run-DkQcMiKXhWz9LjirrRnu/solution[0x8048436]
/lib/i386-linux-gnu/tls/i686/nosegneg/libc.so.6(__libc_start_main+0xf3)[0xb75f44d3]
/run-DkQcMiKXhWz9LjirrRnu/solution[0x80484e9]
======= Memory map: ========
08048000-08049000 r-xp 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
08049000-0804a000 r--p 00000000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
0804a000-0804b000 rw-p 00001000 ca:02 15613970 /run-DkQcMiKXhWz9LjirrRnu/solution
084e2000-08503000 rw-p 00000000 00:00 0 [heap]
b75ba000-b75d6000 r-xp 00000000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d6000-b75d7000 r--p 0001b000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d7000-b75d8000 rw-p 0001c000 ca:01 394527 /lib/i386-linux-gnu/libgcc_s.so.1
b75d8000-b75db000 rw-p 00000000 00:00 0 
b75db000-b777e000 r-xp 00000000 ca:01 394522 /lib/i386-linux- gnu/tls/i686/nosegneg/libc-2.15.so
b777e000-b777f000 ---p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b777f000-b7781000 r--p 001a3000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b7781000-b7782000 rw-p 001a5000 ca:01 394522 /lib/i386-linux-gnu/tls/i686/nosegneg/libc-2.15.so
b7782000-b7789000 rw-p 00000000 00:00 0 
b7789000-b778a000 r-xp 00000000 00:00 0 [vdso]
b778a000-b77aa000 r-xp 00000000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
b77aa000-b77ab000 r--p 0001f000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
b77ab000-b77ac000 rw-p 00020000 ca:01 400153 /lib/i386-linux-gnu/ld-2.15.so
bfe6e000-bfe8f000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)

It wasn't exactly same in all the cases, but pretty much the same. Please help.


回答1:


   int t; char r[3];
   gets(r);

Never ever use gets function. In this case if it receives more than 3 characters (including the terminating null character) you get a buffer overflow.

gets has been removed in the current Standard (C11) and was deprecated in the previous Standard (C99).




回答2:


The code probably entered a 100-character string, which would take 101 bytes to store (including the NUL byte at the end)! Also, never, never use the gets() function in any code that is meant to be robust. Try getline(), which automatically expands the buffer for you.

Also, with backtraces like these you can use addr2line to decode the addresses. Compile with -g and -rdynamic.




回答3:


This

char r[3];
gets(r);

is extremely likely to break for any input of more than 2 characters plus a newline. Note that gets is officially obsoleted by the C standard due to its buffer overflow problem. These days we use something along

char r[42];

if (fgets (r, sizeof r, stdin) != NULL) { ... }

which is safe from overflowing (it rather truncates the input and leaves the rest for the next fgets).



来源:https://stackoverflow.com/questions/14172409/buffer-overflow-detected-in-a-program-that-runs-flawlessly-apparently

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!