I understand this might be an undefined behavior question, but I'm curious and also trying to understand the reason for the below results
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 100
char* memory(){
char ch[SIZE] = {0};
return ch;
}
void copy(char *string){
char *new_string = memory();
strncpy(new_string, string, strlen(string));
}
int main(){
char *string = "This is going to be copied";
copy(string);
}
I am encountering a Segmentation Fault from the Kernel. The memory returned by the memory() function goes out of scope once the function ends, but here’s my understanding: My Understanding:
My Doubts:
Environment:
Operating System: Ubuntu 24.04.1 LTS
Kernel: Linux 6.8.0-49-generic
Architecture: x86-64
Optimization Level 0: gcc ptr.c -g -o ptr -O0
gcc --version gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0
Please let me know if any of my understanding is incorrect.
In addition to the answer by @Nate Eldredge, which answers the main question, you may also get segmentation faults here caused by using the dangerous strncpy
function. Which infamously very few programmers understand how it works let alone what it is actually used for (namely ancient Unix fixed length strings from the 1970s). Details here: Is strcpy dangerous and what should be used instead?
Modified example which is getting rid of the local variable going out of scope and exposing the strncpy
bug:
#include <stdlib.h>
#define SIZE 100
char* memory(){
static char ch[SIZE] = " and the secret password is BAADBEEF";
return ch;
}
void copy(char *string){
char *new_string = memory();
strncpy(new_string, string, strlen(string));
puts(new_string);
}
int main(){
char *string = "This is going to be copied";
copy(string);
}
Output:
This is going to be copied and the secret password is BAADBEEF
With enough strlen to hang yourself, this could as well have been an out of bounds memory access, if there was no tailing byte with value zero in the data as in my hand-crafted example. We could as well have smashed into some stack canary.
Solution:
Never use the dangerous strncpy
function for any purpose (except Unix software archaeology). In this case, one of the safe strcpy
or memccpy
functions should have been used instead.