Reputation: 31
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.
Upvotes: 3
Views: 20229
Reputation: 72746
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
).
Upvotes: 0
Reputation: 516
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
.
Upvotes: 1
Reputation: 145899
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).
Upvotes: 5