Can't find where is the segmentation fault in C program - c

#include<stdio.h>
#include<string.h>
int main()
{
char a[1000000];
int i,j;
int arr[1000000];
gets(a);
unsigned long int len=strlen(a);
if(len<1000000){
for(i=0,j=len-1;i<len&&j>=0;i++,j--)
arr[j]=a[i]-'0';
}
return 0;
}
I am using this code to store the number entered through keyboard into an integer array.But it keeps giving me segmentation fault.I don't know where it is.Plus I've heard gets() isn't a good option,
But I don't know how to use the alternative way to do it. It seems to be a fairly simple code.
Can anyone point where memory is leaking and why?
I have used the debugger on Code::Blocks,the call stack is empty.

The alternative to gets it's fgets:
fgets(a, sizeof(a), stdin);

You have placed two very large arrays on the stack. It's unlikely that your process was launched with a large enough stack (over 5MB). The arrays a and arr should be dynamically allocated using malloc() or calloc() and freed later using free().

Define your array a as follows:
char a[ 1000000 ] = { 0 };
The convention in C for strings is to have a NULL terminator. This ensures two things:
a does not take on values from a previous stack frame.
a has a NULL terminator at the end.
Remark:
Having an array of length 1 million will exhaust your call stack quite quickly.
Consider using a dynamic array to be more space efficient. You would need to read one byte at a time from stdin until EOF or new line is sent, implemented as follows:
for ( int byte = getchar(); byte != EOF && byte != '\n'; byte = getchar() ) {
dynarray_Add( dynArray, byte );
}
... where dynArray_Add would be some function that adds a character to your array of characters and performs the appropriately doubling when the length has reached the capacity.
If you are unfamiliar with a dynamic array, read more here.

There are a number of issues with your code. The most obvious is that you're allocating a huge amount of memory on the stack, which is a bad idea even if it isn't causing a problem in itself. You're also using an old, unsafe function (gets) and you're not doing appropriate error checking.
fgets is almost a drop-in replacement for gets, and it has better safety. Simply call it with fgets( a, 1000000, stdin ), and it will never overrun the size of your buffer. Check the return value against NULL and you won't have uninitialised memory issues. Use malloc to get memory and you won't have stack size issues (don't forget to free!). Finally, don't use ints for your loop when the length is stored as an unsigned long! In this case the size of the buffer means it can't be an infinite loop but it's still bad style (also I think you want size_t not unsigned long - They just happen to be the same on your system).

Related

what will be happen to the size of string in this code?

#include <stdio.h>
#include <stdlib.h>
int main()
{
int size=10;
char string1[50];
char *string2;
string2=(char *)malloc(size*sizeof(char));
fgets(string1,10,stdin);
printf("%s",string1);
fgets(string2,10,stdin);
printf("%s",string2);
}
There are two strings in this code one is an array and another one is dynamically created using pointer.
If my input is less than 50 for string1 and less than 10 for string2 will the space that is not filled get wasted ,if so how to reduce the size.
In case of string 2 malloc size parameter is 10 and fgets size parameters is 10 what will happen if i increase the size to fgets(string2,50,stdin) which is greater than malloc's size?
how to calculate the final size of input string in each case?I have used sizeof operator but it gave the hardcoded size that is 50 and 10 respectively for string1 and string2
Is there any other better approach to create a dynamic string?
Yes, it will be wasted. You can use variable-length arrays to use a different limit, or use dynamic allocation. Whether or not you should worry about the wasted space is a separate question: if your program reads strings that the user inputs manually (as opposed to reading a file) you can waste a lot of space before it starts to matter, unless you are on an embedded system with severe memory constraints.
You will get undefined behavior, so your program will be invalid. Don't do that - it is precisely why fgets takes the maximum length of the string.
Call strlen to compute the length of the string. Add 1 for null terminator. Remember that '\n' is part of the string when you use fgets and the input has '\n' in it.
You can use POSIX extension to scanf, and pass %ms format and a pointer to char*. This will allocate the string at the exact length, but your program will be less portable. Obviously, you are required to deallocate these strings to avoid memory leaks.

Heap Overflow Attack

I am learning about heap overflow attacks and my textbook provides the following vulnerable C code:
/* record type to allocate on heap */
typedef struct chunk {
char inp[64]; /* vulnerable input buffer */
void (*process)(char *); /* pointer to function to process inp */
} chunk_t;
void showlen(char *buf)
{
int len;
len = strlen(buf);
printf("buffer5 read %d chars\n", len);
}
int main(int argc, char *argv[])
{
chunk_t *next;
setbuf(stdin, NULL);
next = malloc(sizeof(chunk_t));
next->process = showlen;
printf("Enter value: ");
gets(next->inp);
next->process(next->inp);
printf("buffer5 done\n");
}
However, the textbook doesn't explain how one would fix this vulnerability. If anyone could please explain the vulnerability and a way(s) to fix it that would be great. (Part of the problem is that I am coming from Java, not C)
The problem is that gets() will keep reading into the buffer until it reads a newline or reaches EOF. It doesn't know the size of the buffer, so it doesn't know that it should stop when it hits its limit. If the line is 64 bytes or longer, this will go outside the buffer, and overwrite process. If the user entering the input knows about this, he can type just the right characters at position 64 to replace the function pointer with a pointer to some other function that he wants to make the program call instead.
The fix is to use a function other than gets(), so you can specify a limit on the amount of input that will be read. Instead of
gets(next->inp);
you can use:
fgets(next->inp, sizeof(next->inp), stdin);
The second argument to fgets() tells it to write at most 64 bytes into next->inp. So it will read at most 63 bytes from stdin (it needs to allow a byte for the null string terminator).
The code uses gets, which is infamous for its potential security problem: there's no way to specify the length of the buffer you pass to it, it'll just keep reading from stdin until it encounters \n or EOF. It may therefore overflow your buffer and write to memory outside of it, and then bad things will happen - it could crash, it could keep running, it could start playing porn.
To fix this, you should use fgets instead.
You can fill up next with more than 64 bytes you will by setting the address for process. Thereby enable one to insert whatever address one wishes. The address could be a pointer to any function.
To fix simple ensure that only 63 bytes (one for null) is read into the array inp - use fgets
The function gets does not limit the amount of text that comes from stdin. If more than 63 chars come from stdin, there will be an overflow.
The gets discards the LF char, that would be an [Enter] key, but it adds a null char at the end, thus the 63 chars limit.
If the value at inp is filled with 64 non-null chars, as it can be directly accessed, the showlen function will trigger an access violation, as strlen will search for the null-char beyond inp to determine its size.
Using fgets would be a good fix to the first problem but it will also add a LF char and the null, so the new limit of readable text would be 62.
For the second, just take care of what is written on inp.

How to XOR two byte streams in C?

I've been reading through SO for the past couple of days trying to figure this out, I am stumped. I want to read in two 32 bit byte arrays (from stdin, input will be hex) and xor them, then print the result.
So far I've tried using scanf, fgets, and gets. My thought was to read the large hex numbers into a char buffer and perform the xor in a for loop until I hit an EOL (with fgets) or a null terminator. So far my output is not even close. I tried lots of variations, but I will only post my latest fail below. The challenge I've been trying to complete is: http://cryptopals.com/sets/1/challenges/2/
I am trying it in C because I'm really trying to learn C, but I'm really getting frustrated with none of these attempts working.
#include <stdio.h>
#include <math.h>
int main()
{
char buff1[100];
char buff2[100];
char buff3[100];
int size = sizeof(buff1);
puts("Enter value\n");
fgets(buff1, size, stdin);
puts(buff1);
puts("Enter value\n");
fgets(buff2, size, stdin);
puts(buff2);
for (int i = 0; i != '\n'; i++) {
buff3[i] = buff2[i] ^ buff1[i];
printf("%x", buff3[i]);
}
return 0;
}
When using sizeof() it should be used with types, not data. For instance if you want space for 100 chars, you need to find the sizeof(char) and then multiply by 100 to find out how many bytes you need and that goes into the buffer. A char is usually a byte so expect 100 bytes. fgets() will work but I prefer to use this
int getchar()
Just stop when the the user
enters a newline/terminator character. Since you don't know how many characters will come in from stdin, you
need to dynamically increase the size of your buffer or it will overflow. For the purposes of this question you can just make it a very big array, check to see if its about to overflow and then terminate the program. So to recap the steps.
1.) Create a big array
2.) While loop over getchar() and stop when the output is the terminator, take note of
how many chars you read.
3.) Since both buffers are guaranteed to have equal chars make your
final array equal to that many chars in size.
4.) For loop over getchar() and as the chars come out, xor them with the first array
and put the result into the final array. You should try doing this with 1 array
afterwards to get some more C practice.
Good luck!
EDIT:
fgets() can be used but depending on the implementation it is useful to know how many chars have been read in.
#include <string.h>
#include <ctype.h>
static inline unsigned char hc2uc(char d){
const char *table = "0123456789abcdef";
return strchr(table, tolower(d)) - table;
}
...
for(int i=0;buff1[i]!='\n';i++){
buff3[i]=hc2uc(buff2[i])^hc2uc(buff1[i]);
printf("%x",buff3[i]);
}

How to declare a char array of size same as the size of the string entered at the runtime in C?

I want to get a string from the user, in a char array that have no fixed length. The length should be equal to the, length of the string that the user enters. I tried malloc(), but that also requires the size to be specified. Please help.
Please mark it, I want to use a char array, not a string type.
C strings do not pack their length with them. Every C string is a plain array of characters, with a null after the last char to indicate its end. Standard functions from the C IO library will generally receive, therefore, an array of chars and write data into it. The array will have to be big enough to hold everything that is typed by the user. Most functions won't even check for buffer overflows.
Now what you can do is ask first for the max length of the string the user is going to type and allocate exact memory, or you can declare a huge array and define its size as the max string length.
char bigBuffer[2048];
fgets(bigBuffer, 2048, stdin);
fgets() allows you to specify the maximum number of chars you are taking in. If the user types more than 2048 chars, in this example, fgets() it will return with an error and prevent your program from crashing.
It is not possible to allocate a memory with infinite length. Every memory is bound by size one way or other.
There are two ways to handle your situation.
1. Allocate a large memory which will not overrun any possible user input.
2. [Better Option] Use reasonable size memory and use function with length check like, fgets, to get user input.
What you need is a basic unlimited input function. The idea is to allocate a reasonably sized buffer for input, begin reading one char at a time, and if you exceed the buffer size to realloc it and increase its size.
You could optimize this a bit by reading strings the length of the remaining space, but that gets complicated and fiddly. Mainly not worth it.
I wrote this code off the top of my head so it probably won't compile and work as-is, but it should give you the basic idea.
char *buffer = malloc(100);
size_t bufferLen = 100;
size_t currLen = 0;
int c;
while ((c = getchar()) != EOF && c != '\n')
{
if (currLen > bufferLen-1) // -1 because must leave room for null terminator
{
bufferLen += 100;
buffer = realloc(buffer, bufferLen);
buffer[currLen++] = c;
}
else
buffer[currLen++] = c;
}
buffer[currLen] = '\0';
This can be done in indirect way.
Read one character at a time from input. Using malloc/realloc allocate memory in increasing fashion. It is not of constant order time and constant order memory algo but your functionality can be achieved.
Here is the code snippet for that.
char ch;
int count=0;
char *charArray=NULL;
printf("Enter string\n");
while((ch=getchar())!='\n')//This condition can be changed according to needs
{
count=count+1;
charArray=(char *)realloc(charArray,count);
charArray[count-1]=ch;
}
You create the array after the user has entered the string. Can't remember exact C syntax but something along the lines of
string word = "";
scanf("%s", word");
char myArray[word.length];

Need help with malloc in C programming. It is allocating more space than expected

Let me preface this by saying that i am a newbie, and im in a entry level C class at school.
Im writing a program that required me to use malloc and malloc is allocating 8x the space i expect it to in all cases. Even when just to malloc(1), it is allocation 8 bytes instead of 1, and i am confused as to why.
Here is my code I tested with. This should only allow one character to be entered plus the escape character. Instead I can enter 8, so it is allocating 8 bytes instead of 1, this is the case even if I just use a integer in malloc(). Please ignore the x variable, it is used in the actual program, but not in this test. :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc ,char* argv[]){
int x = 0;
char *A = NULL;
A=(char*)malloc(sizeof(char)+1);
scanf("%s",A);
printf("%s", A);
free(A);
return 0;
}
A=(char*)malloc(sizeof(char)+1);
is going to allocate at least 2 bytes (sizeof(char) is always 1).
I don't understand how you are determining that it is allocating 8 bytes, however malloc is allowed to allocate more memory than you ask for, just never less.
The fact that you can use scanf to write a longer string to the memory pointed to by A does not mean that you have that memory allocated. It will overwrite whatever is there, which may result in your program crashing or producing unexpected results.
malloc is allocating as much memory as you asked for.
If you can read more than the allocated bytes (using scanf) it's because scanf is reading also over the memory you own: it's a buffer overflow.
You should limit the data scanf can read this way:
scanf( "%10s", ... ); // scanf will read a string no longer than 10
Im writing a program that required me
to use malloc and malloc is allocating
8x the space i expect it to in all
cases. Even when just to malloc(1), it
is allocation 8 bytes instead of 1,
and i am confused as to why.
Theoretically speaking, the way you do things in the program, is not allocating 8 bytes.
You can still type in 8 bytes (or any number of bytes) because in C there is no check, that you are still using a valid place to write.
What you see is Undefined Behaviour, and the reason for that is that you write in memory that you shouldn't. There is nothing in your code that stops the program after n byte(s) you allocated have been used.
You might get Seg Fault now, or later, or never. This is Undefined Behaviour. Just because it appears to work, does not mean it is right.
Now, Your program could indeed allocate 8 bytes instead of 1.
The reason for that is because of Alignment
The same program might allocate a different size in a different machine and/or a different Operating System.
Also, since you are using C you don't really need to cast. See this for a start.
In your code, there is no limit on how much data you can load in with scanf, leading to a buffer overflow (security flaw/crash). You should use a format string that limits the amount of data read in to the one or two bytes that you allocate. The malloc function will probably allocate some extra space to round the size up, but you should not rely on that.
malloc is allowed to allocate more memory than you ask for. It's only required to provide at least as much as you ask for, or fail if it can't.
using malloc or creating a buffer on the stack will allocate memory in words.
On a 32-bit system the word size is 4 bytes, so when you ask for
A=(char*)malloc(sizeof(char)+1);
(which is essentially A=(char*)malloc(2);
the system will actually give you 4 bytes. On a 64-bit machine you should get 8 bytes.
The way you use scanf there is dangerous as it will overflow the buffer if a string greater than the allocated size leaving a heap overflow vulnerability in your program. scanf in this case will attempt to stuff a string of any length in to that memory so using it to count the allocated size will not work.
What system are you running on? If it's 64 bit, it is possible that the system is allocating the smallest possible unit that it can. 64 bits being 8 bytes.
EDIT: Just a note of interest:
char *s = malloc (1);
Causes 16 bytes to be allocated on iOS 4.2 (Xcode 3.2.5).
If you enter 8 if will just allocate 2 bytes sizeof(char) == 1 (unless you are on some obscure platform) and you will write you number to that char. Then on printf it will output the number you stored in there. So if you store the number 8 it'll display 8 on the command line. It has nothing to do with the count of chars allocated.
Unless of course you looked up in a debugger or somewhere else that it is really allocating 8 bytes.
scanf has no idea how big the target buffer actually is. All it knows is the starting address of the buffer. C does no bounds checking, so if you pass it the address of a buffer sized to hold 2 characters, and you enter a string that's 10 characters long, scanf will write those extra 8 characters to the memory following the end of the buffer. This is called a buffer overrun, which is a common malware exploit. For whatever reason, the six bytes immediately following your buffer aren't "important", so you can enter up to 8 characters with no apparent ill effects.
You can limit the number of characters read in a scanf call by including an explicit field width in the conversion specifier:
scanf("%2s", A);
but it's still up to you to make sure that target buffer is large enough to accomodate that width. Unfortunately, there's no way to specify the field width dynamically as there is with printf:
printf("%*s", fieldWidth, string);
because %*s means something completely different in scanf (basically, skip over the next string).
You could use sprintf to build your format string:
sprintf(format, "%%%ds", max_bytes_in_A);
scanf(format, A);
but you have to make sure the buffer format is wide enough to hold the result, etc., etc., etc.
This is why I usually recommend fgets() for interactive input.

Resources