Segmentation fault about data type? - c

I find out that my code only works with n <= 43429. If n>43429, it causes a segmentation fault. Did I wrong with the data type or anything?
here is my code and debug result:
enter image description here
#include<stdio.h>
#include<windows.h>
double recursive(long n);
int main(){
printf("\nEnter n:");
long n; scanf("%ld", &n);
printf("\n%.2lf", recursive(n));
getch();
return 0;
}
double recursive(long n){
if(n<=1) return 1;
else return (double)1/n + recursive(n-1);
}

Every recursive call requires space on the call stack (often referred to as just "the stack"). The stack has a fixed maximum size. If you use up all of the space in the stack, the program crashes. Your OS and/or your compiler default to making the stack big enough for 43429 recursive calls, but not more.
There is usually a way to request more space for the stack, but not from within the program. On Windows you specify the needed size in the "module .def file". I am not familiar with the IDE you are using, but that should translate to a knob in the project configuration somewhere.
Alternatively, this would be a good time to learn how to convert recursion to iteration. Your program is almost tail recursive so it's an easy case.
I don't know how you managed to get Windows to report this crash using the phrase "Segmentation fault", but that's not important right now.

Related

pointer problems in C? function to order inputs, return as string and print in main

I want to write a function that will take two integers, three times, and then return them ordered by the first integer and (for now) print them in main (though eventually I plan/hope to switch to a file-based structure to store and organize data), but I think I might have an issue with my pointers cause even when I skip concatenations (which looks like might also be another separate issue), everything Ive tried has main print a string (or no string) which never matches the input, but the print statements suggest all the looped assignments are working properly.
#include <stdio.h>
#include <string.h>
const char * entry()
{
int n;
int level;
char habit1entry[6];
char habit2entry[6];
char habit3entry[6];
for (int c = 0; c< 3; c++){
printf("Habit #\n");
scanf("%d", &n);
printf("Level:\n");
scanf("%d", &level);
switch (n)
{
case 1:;
sprintf(habit1entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit1entry);
continue;
case 2:;
sprintf(habit2entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit2entry);
continue;
case 3:;
sprintf(habit3entry, "|%d|%d|\n", n,level);
printf("n = %d\n",n);
printf("%s\n",habit3entry);
continue;
}
}
strcat(habit2entry,habit3entry);
printf("%s\n",habit2entry);
strcat(habit1entry,habit2entry);
printf("%s\n",habit1entry);
char *fullEntry=habit3entry;
printf("%s\n",fullEntry);
return strdup(&fullEntry[0]);
}
int main(){
const char * dataEntry = entry();
//strcpy(dataEntry,entry());
printf("Data:\n%s",dataEntry);
}
heres an example of the output(after the correct prints inside the switch cases) for an input of 3 2 1 1 2 2:
"
|2|2|
|1|1|
|2|2|
|2|2|
|��
|2|2|
|��
* stack smashing detected *: ./a.out terminated
Aborted (core dumped) "
p.s. Sorry if this all sounds silly, this is my first C project (and first real stack overflow post, plz b gentl) coming from jumping around between java, python and clojure and I would like to take an operating systems class that allows you to start without knowing C but expects you to pick it up on your own and its hard finding material that explains C concepts in a scope that matches my background knowledge and current learning constraints in terms of time available for taking deep dives through explanations that for me have ended up mostly being either hopelessly esoteric, incredibly case-specific or overly-simplistic/redundant/unhelpful explanations of programming concepts I picked up in other languages. Dont mean to complain or harp on and its probably good to get practice with different methods of asking questions and finding answers for problems like these, but the learning curve for understanding things like this (setting up the compiler/json files involved spending hours only to discover that mcafee was deleting my exes which I became convinced was a symptom of a virus, only to have the behavior stop after I restarted for a minor routine windows update and I have no idea why) outside of a traditional framework sometimes seems more like a wall and I'm worried that maybe I should revise my approach to avoid wasting too much of my time banging my head against a series of very sturdy walls. any and all advice is greatly appreciated.
Abstracting form the logic of the program, you have plenty of issues there:
You do not provide enough space for the strings
Your switch is not very related to your for loop
Names of the variables do not matter for you - but they matter for the program . Be more careful.
probably more but I forgot already
#include <stdio.h>
#include <string.h>
const char * entry()
{
int n;
int level;
char habit1entry[21] = "";
char habit2entry[14] = "";
char habit3entry[7] = "";
for (int c = 1; c < 4; c++){
printf("Habit #\n");
scanf("%d", &n);
printf("Level:\n");
scanf("%d", &level);
switch (c)
{
case 1:;
sprintf(habit1entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He1: %s\n",habit1entry);
continue;
case 2:;
sprintf(habit2entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He2 = %s\n",habit2entry);
continue;
case 3:;
sprintf(habit3entry, "|%d|%d|\n", n,level % 10);
printf("n = %d\n",n);
printf("He3 = %s\n",habit3entry);
continue;
}
}
strcat(habit2entry,habit3entry);
printf("H2 + H3 = %s\n",habit2entry);
strcat(habit1entry,habit2entry);
printf("H1 + H2 = %s\n",habit1entry);
char *fullEntry=habit1entry;
printf("FE: %s\n",fullEntry);
return strdup(fullEntry);
}
int main(){
const char * dataEntry = entry();
//strcpy(dataEntry,entry());
printf("Data:\n%s",dataEntry);
}
Welcome to the weird and wonderful world of C.
I have not actually compiled and run your program yet, just had a quick read through and though I give you my first thoughts.
The way your program is written is primed to generate stack overflows. You have three (very little) character arrays defined on the stack habitxentry, so your sprintf's will most certainly blow your stack unless both the Habit and Level inputs are less than 10. Habit is alright because your switch only allows 1, 2 or 3. Your switch does nothing if Habit is anything else.
As a side note: sprintf is not really the function to use in our security minded world. snprintf is a better choice. Not really an issue here per se as you are not passing in user supplied data but still, it's not a good habit to cultivate.
Next you strcat your character arrays together, virtually guarantying a stack violation, but lets assume this works; you are concatenating 2 and 3 into habit2entry and then 1 and 2 into habit1entry.
Next you are creating a pointer to habit3entry (not habit1entry) and returning a duplicate.
By doing so you are allocating heap in a mildy obscure manner. The callee will be responsible for freeing this memory.
I always preferred to explicitly malloc the memory and then strcpy (or memcpy) the data in.
Now when you grep your code, you only have to look for malloc.
Also, someone using the function will notice the malloc, see you have returned to pointer and realize that freeing it will now be his problem.
In order to avoid these problems some programmers leave it to the caller to supply a buffer to the function. The reasoning is that a function is supposed to do one thing and one thing only. In this case you are doing two things, you allocate memory and you fill that memory.
In your switch statement I noticed that each of your case labels are followed by an empty statement.
the semicolon at the end of that line is not necessary: write "case 1:" not "case 1:;"
You also use continue at the end of each block. This is allowed but "break" is more appropriate.
In this case it will have the same effect but normally you have more statements after the switch.
Now the difference will become apparent. Continue will jump straight to the top of the loop, break will break out of the switch and continue executing there.
Hope this gives you some insight.
Good luck.

Recursive function, passing arguments - segmentation fault

I am writing a program for multiplying big numbers using a karatsuba algorithm.
There is a recursive function.
Right before the recursive call I print string values and they are ok. Then, inside this function at the beginning I print the passed arguments again (I should get exactly the same results as before recursive call, earlier printf()) and I get segmentation fault.
This happen not on first function execution, but after many recursive calls.
My code:
void karatsuba(char *result, char *first, char *second)
{
printf(" %s %s\n", first, second);
<somewhere here conditional return to end recursion>
...
...
printf(" %s %s\n", temp_first, temp_second);
karatsuba(temp, temp_first, temp_second);
...
...
}
What do can cause segmentation fault in that case?
UPDATE:
Thank you all for your answers. Stack overflow is propably the reason.
I created a static counter incremented at the start of recursive function and decremented at each of function ends and printed it. At the segmentation fault its value indicated depth of 46778.
Then, I increased stack size as Graham Borland pointed to 32MB. Now, counter indicated depth of 159126 calls, so increasing stack size made it better.
Sum of data in this function is 140B. Multiplying this value by stack depth gives me 21MB, which is less than 32MB.
After all, this number of recursive calls is too big. Doing calculation on paper I go maximum into <10 recursive calls for my data. Propably infinite recursion. :(
You are likely to be busting the stack. Depending on the platform, you may be able to increase the stack available to your process. For example, on a Unix-like platform, entering this at the bash prompt before running your program:
ulimit -s 32768
will increase the stack to 32MB.
The most probable reason is:
Stack Overflow
Infinite recursion??

Is there any hard-wired limit on recursion depth in C

The program under discussion attempts to compute sum-of-first-n-natural-numbers using recursion. I know this can be done using a simple formula n*(n+1)/2 but the idea here is to use recursion.
The program is as follows:
#include <stdio.h>
unsigned long int add(unsigned long int n)
{
return (n == 0) ? 0 : n + add(n-1);
}
int main()
{
printf("result : %lu \n", add(1000000));
return 0;
}
The program worked well for n = 100,000 but when the value of n was increased to 1,000,000 it resulted in a Segmentation fault (core dumped)
The following was taken from the gdb message.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004004cc in add (n=Cannot access memory at address 0x7fffff7feff8
) at k.c:4
My question(s):
Is there any hard-wired limit on recursion depth in C? or does the recursion depth depends on the available stack memory?
What are the possible reasons why a program would receive a reSIGSEGV signal?
Generally the limit will be the size of the stack. Each time you call a function, a certain amount of stack is eaten (usually dependent on the function). The eaten amount is the stack frame, and it is recovered when the function returns. The stack size is almost almost fixed when the program starts, either from being specified by the operating system (and often adjustable there), or even being hardcoded in the program.
Some implementations may have a technique where they can allocate new stack segments at run time. But in general, they don't.
Some functions will consume stack in slightly more unpredictable ways, such as when they allocate a variable-length array there.
Some functions may be compiled to use tail-calls in a way that will preserve stack space. Sometimes you can rewrite your function so that all calls (Such as to itself) happen as the last thing it does, and expect your compiler to optimise it.
It's not that easy to see exactly how much stack space is needed for each call to a function, and it will be subject to the optimisation level of the compiler. A cheap way to do that in your case would be to print &n each time its called; n will likely be on the stack (especially since the progam needs to take its address -- otherwise it could be in a register), and the distance between successive locations of it will indicate the size of the stack frame.
1)Consumption of the stack is expected to be reduced and written as tail recursion optimization.
gcc -O3 prog.c
#include <stdio.h>
unsigned long long int add(unsigned long int n, unsigned long long int sum){
return (n == 0) ? sum : add(n-1, n+sum); //tail recursion form
}
int main(){
printf("result : %llu \n", add(1000000, 0));//OK
return 0;
}
There is no theoretical limit to recursion depth in C. The only limits are those of your implementation, generally limited stack space.
(Note that the C standard doesn't actually require a stack-based implementation. I don't know of any real-world implementations that aren't stack based, but keep that in mind.)
A SIGSEGV can be caused by any number of things, but exceeding your stack limit is a relatively common one. Dereferencing a bad pointer is another.
The C standard does not define the minimum supported depth for function calls. If it did, which is quite hard to guarantee anyway, it would have it mentioned somewhere in section 5.2.4 Environmental limits.

Segmentation fault in file parsing code

I am getting a segmentation fault when I try to run my program that does matrix addition. I am trying to run the program separately ~1000 times (while timing each run and writing the result to a file).
The problem is, I get segmentation fault after a number of runs - how far I get depends on the size of the matrix. For example, if I run a 10x10 matrix (each instance has randomly generated numbers), I get segmentation fault after exactly 1013 runs. For a 100x100 matrix, I get a segfault at 260 runs.
A quick run through of how the program works is as follows:
Numbers are randomly generated and written to a file depending on the entered input (10x10, 100x100)
The numbers are read in from the file and send to CUDA*
CUDA calculates the results and writes it to a results file (and also times how long the calculation took and writes it to another file)
*This step appears to be causing the segmentation fault according to the GDB debugger. Below is the error output from the debugger and the function that is causing the error.
>Program terminated with signal 11, Segmentation fault.
#0 0x0000000000402f4c in readFromFile(int, char, int&, int&, float*) ()
Here is the actual function:
void readFromFile(int fd, char byte, int &matrixWidth, int &matrixHeight,float *matrix)
{
int tokenIndex = 0;
char *token = (char*) malloc(500);
int matrixIndex = 0;
while(read(fd,&byte,1)){
if(isdigit(byte)||byte=='.'){
token[tokenIndex]=byte;
tokenIndex++;
}
else if(byte==' ' && matrixHeight==0){
matrixWidth++;
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
//printf("Stored: %d\n",matrixOne[matrixIndex]);
tokenIndex=0;
matrixIndex++;
}
else if(byte=='\n'){
matrixHeight++;
if(tokenIndex!=0){
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
//printf("Stored: %d\n",matrixOne[matrixIndex]);
tokenIndex=0;
matrixIndex++;
}
}
else if(byte==' ' && matrixHeight!=0){
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
tokenIndex=0;
matrixIndex++;
}
//printf("Token: %s, number matrix: %f\n" , token, matrix[matrixIndex-1]);
}
}
This code is repeatedly run until the segmentation fault (each time the file it reads has different numbers). If you need any more code, just let me know. Any help would greatly be appreciated.
There are many problems that could cause the segmentation fault in the code you posted. Let me list a few:
As Jens pointed out how sure are you that the size of any token is actually < 500 characters
How sure are you that there are no run-on numbers like 1.32.4? ATOF could crash on this so use strtod instead
Use a debugger to run the program as macs pointed out that will give you the line that it crashed on and you can see the values of the variables so it gives you a better idea
Use safety checks when reading the input as the run-on numbers could be the least of the problems. Multiple '\n' characters could mess it up.
Since everything is text I would suggest you read using fscanf rather then building your own version.
Read up on Row major vs. Column Major formats depending on what the data might be you may not need to keep track of dimensions
How do you allocate the memory for the matrix? Equally important, do you free it? Anyway, a hint: compile your program with -g option to generate debug information, and learn how to use a debugger. Then you will find the problem, whereas we can just guess.

Stack Overflow Exploit in C

The question is actually about stack overflows in C.
I have an assigment that I can not get done for the life of me, I've looked at everything in the gdb and I just cant figure it.
The question is the following:
int i,n;
void confused()
{
printf("who called me");
exit(0);
}
void shell_call(char *c)
{
printf(" ***Now calling \"%s\" shell command *** \n",c);
system(c);
exit(0);
}
void victim_func()
{
int a[4];
printf("[8]:%x\n", &a[8]);
printf("Enter n: "); scanf("%d",&n);
printf("Enter %d HEX Values \n",n);
for(i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n");
}
int main()
{
printf("ls=736c --- ps = 7370 --- cal = 6c6163\n");
printf("location of confused %x \n", confused);
printf("location of shell_call %x \n", shell_call);
victim_func();
printf("Done, thank you\n");
}
Ok, so I managed to get the first question correctly, which is to arbitrarily call one of the two functions not explicitly called in the main path. By the way, this has to be done while running the program without any modifications.
I did this by running the program, setting N to 7, which gets me to the Function Pointer of the victim_func frame, I write a[7] with the memory address of confused or shell_call, and it works. (I have a 64 bit machine, thats why I have to get it to 7, since the EBI pointer is 2 ints wide, instead of 1)
My question is the following, how could I control which argument gets passed to the shell_code funcion? ie. how do I write a string to char* c.
The whole point is executing unix commands like ps etc, by running only the program.
I figured writing the EBI pointer with the hex representation of ps and setting the arg list of shell_call to that, but that didn't work. I also tried inputing argsv arguments and setting the arg list of shell_call to the arg_list of main, but didn't work either.
I think the second version should work, but I believe I'm not setting the arg list of the new stack frame correctly ( I did it by writing a[8] to 0, since its the first part of the function pointer, and writing a[9]=736c and a[10]=0000, but its probably not right since those are the parameters of victim_func. So how do I access the parameters of shell_call?
I probably shouldn't do your homework for you. But the basically:
You need to get a character buffer somewhere in memory to store the string you want to execute. Obviously, you can do this the same way you are getting the other functions called (i.e. you put the text on the stack as well). After you have that written, you need to write a pointer to it on to the stack in the location that the shell_code function expects to find its arguments.
The best way to figure this out without me doing all of the work for you is to write down your stack/memory contents on a piece of paper/whiteboard. Write down how it would look if you called shell_code normally from inside the program. Then write down what the stack looks like inside victum_func and figure out which things to change to get it to look like it would look "naturally" (of course keeping in mind some things are "don't cares" like the return address).
That's all the charity you're gonna get from me today! :-P
SoapBox already did a great job of leading you in the right direction.
For more information;
http://www.skullsecurity.org/wiki/index.php/Example_4
You need to manipulate the stack-frame of the caller (main()), and arrange it in such a way that returning to shell_call() from the epilog of the overflowed victim_func() the latter could find a settled stack as it was been called by the main.
In doing so you probably have to mangle the frame-pointer in the stackframe of the victim, that will be restored in %ebp by means of leave.

Resources