Stack smashing detected in C++ is an error message generated by the C or Cpp compilers like GCC and many runtime environments when buffer overflow occurs or when someone tries to store more amount of data in a fixed amount of memory. At the same time, it behaves as a security mechanism to alert the users and developers saying that there's been an attempt to corrupt the program's stack, which is a very common sign of malicious activity. After showing this stack smashing detected error, the program that is currently running will be terminated to prevent further execution and save from malicious risks.
There are many cases where this error is likely to occur. Some of them are listed below:
- Buffer overflow
- Incorrect use of string functions
- Function pointer manipulation
- Recursion without the base case
- Malicious input handling
- Array index out of bounds
- Incorrect use of pointer
- Incorrect use of standard library containers
- Using pointers unsafely
- Incorrect use of smarcpp tutorialers
Now, we will discuss each case with an example code:
1. Buffer Overflow:
Every buffer is allocated with some fixed stack space . When a program writes more data into the buffer than the allocated fixed size, it causes the buffer to overflow. It means writing beyond the allocated memory corrupts the stack, which leads to the stack smashing.
Example:
#include <cstring>
int main() {
char buffer[10];
strcpy(buffer, "This is a buffer overflow attack!");
return 0;
}
Output:
Program which avoids the stack smashing detected error:
#include <iostream>
#include <cstring>
int main() {
char buffer[10];
strncpy(buffer, "Safe Copy", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
return 0;
}
Output:
3. Incorrect use of the string functions:
Some string inbuilt functions like strcpy and strcat, when used without the proper bounds checking, will cause the buffer overflow. As these functions do not check the size of the destination buffer, making buffer overflow and override the adjacent memory blocks.
4. Function pointer manipulation:
This error is shown when a program attempts to call a function through a manipulated or corrupted function pointer. It usually happens when an attacker or a bug in the program will alter the function pointer's value. Pointing it to an unintended location or a non-function address.
Example:
A program that causes the error:
#include <iostream>
#include <cstring>
using namespace std;
void vulnerableFunction(const char* input) {
char buffer[10];
strcpy(buffer, input);
cout << "Buffer content: " << buffer << endl;
}
int main() {
void (*functionPtr)(const char*) = vulnerableFunction;
const char* maliciousInput = "Malicious Input Overflows the Buffer!";
functionPtr(maliciousInput);
return 0;
}
Output:
Program which avoids the stack smashing detected error:
#include <iostream>
#include <cstring>
using namespace std;
void saferFunction(const char* input) {
char buffer[11];
strncpy(buffer, input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
cout << "Buffer content: " << buffer << endl;
}
int main() {
void (*functionPtr)(const char*) = saferFunction;
const char* safeInput = "Safe Input";
functionPtr(safeInput);
const char* maliciousInput = "Malicious Input Overflows the Buffer!";
functionPtr(maliciousInput);
return 0;
}
Output:
4. Recursion without base case
base case or base condition are used in the recursion for stopping the further recursion and returning the required result to the called function. If the base condition is not met then the recursion will not stop. It throws the stack overflow error. This error is due to the filling of function calls in the stack. To avoid the error we can use proper base condition for any type of the recursion
Example:
A program that causes the error:
#include <iostream>
using namespace std;
void recursiveFunction(int n) {
cout << n << endl;
recursiveFunction(n + 1); // Recursive call without a base case
}
int main() {
recursiveFunction(1);
return 0;
}
Output:
Program which avoids the stack smashing detected error:
#include <iostream>
using namespace std;
void recursiveFunction(int n) {
if (n <= 0) {
return; // Base case to terminate recursion
}
cout << n << endl;
recursiveFunction(n - 1);
}
int main() {
recursiveFunction(5);
return 0;
}
Output:
5. Malicious input handling:
If the user is not correctly validated, it allows the attackers to input excessively long strings. So, the attackers will send the long strings to overflow buffers, causing stack smashing.
6. Array Index Out Of Bounds:
If an array goes out of its fixed size, we get an array index out-of-bounds error . When someone tries to access the element using an index that is not present in the array, we get the array index out of bounds. When we write the elements to the array even after the length of the array is exceeded, we get the array index out-of-bounds error, which causes the stack smashing error.
7. Incorrect use of pointers:
Improper dereferencing or manipulation of pointers can lead to writing data into unintended memory locations. Writing data to unintended memory addresses can corrupt the stack or other program data structures.