Help interpreting gdb: segfault in function - c

I am trying to debug a segfault, and I have this output from gdb:
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x08048af9 in parse_option_list (ptr=0x6f72505f <Address 0x6f72505f out of bounds>, box_name=0x696d6978 <Address 0x696d6978 out of bounds>, option_list=0x313a7974,
num_elements=0x33313532) at submit.c:125
125 memcpy(&(option_list[(*num_elements)].value), value, 24);
(gdb) p num_elements
$15 = (int *) 0x33313532
(gdb) p *num_elements
Cannot access memory at address 0x33313532
(gdb)
It looks to me like something in memcpy() is going haywire. But I can't figure out what exactly the problem is, since that line references so many variables.
Can somebody help figure out what the 0x8048af9 in parse_option_list... line is telling me?
My function signature is:
int parse_option_list(char *ptr, char *box_name,
struct option_list_values *option_list, int *num_elements)
And this might be useful:
struct option_list_values {
char value[24];
char name[24];
};
Also, the variables value and name are not segfaulting (but if you think they are, i can post the code which sets those values.) But right now, if I can understand this gdb output, I will be happy as a clam! Thank you!

You have all the signs of a classic buffer overflow. The values of all the stack parameters have been overwritten by ASCII text - here is the translation of those values (assuming you have a little-endian architecture, which looks right):
ptr = 0x6f72505f = "_Pro"
box_name = 0x696d6978 = "ximi"
option_list = 0x313a7974 = "ty:1"
num_elements = 0x33313532 = "2513"
Concatenating them together gives "_Proximity:12513" - if this substring looks familiar to you, you should be able to track down where that data is being copied around - somewhere you are copying it into an array stored on the stack, without proper bounds checking.

0x8048af9 is the instruction pointer - the address of the executable code in memory that your code was at when the SEGFAULT occurred.
Are you sure that option_list[(*num_elements)].value is a valid address? You might have a buffer overflow, and be overwriting something you shouldn't be.
If num_elements is the length of option_list, then option_list[(*num_elements)] refers to just after the end of the list.

ptr=0x6f72505f - Address 0x6f72505f out of bounds
This is the useful part in this case
The first input to parse_option_list is invalid. Possibly an uninitialized pointer.

Related

Why does the execution of this basic program gives an error?

I don't really understand, why does the execution of this program give an error?
int main()
{
char *b;
*b='2';
printf("%c",*b);
return 0;
}
As it stands, b is uninitialized and thus may point to any arbitrary location. When you say *b =..., you are trying to write to some unspecified location, which (depending on what that location is) often causes an error (say a segfault). Perhaps you meant to declare b as a char instead of a pointer to one?
This looks like its taken straight from homework or a textbook. When you declare the char pointer b, it is not given a memory address (where it points to) by default, it just contains whatever was in the memory location beforehand. This means that if you attempt to work with the value (*b = '2' or printf) it will try to read this random information left over in memory as an address and look for a char at that address. This would cause a segmentation fault or if you're unlucky, it would grab garbage from the memory and use it as a char value.
The solution would be to create a char variable (char a) and set the pointer to the location of a (b = &a).
Hopefully this helps, and good luck on your studies.

segmentation fault at av_frame_get_side_data

When I executed the following code:
AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[]
AVFrame *avf1 = &tmp;
AVFrameSideData* avfsd1=NULL;
if(avf1->side_data != NULL)
printf("avf1->side_data is not NULL!!...........\n");
avfsd1 = av_frame_get_side_data(avf1, AV_FRAME_DATA_MOTION_VECTORS);
I came across segmentation fault happened at av_frame_get_side_data(avf1, AV_FRAME_DATA_MOTION_VECTORS):
avf1->side_data is not NULL!!...........
Segmentation fault (core dumped)
why?
here is the output of gdb:
(gdb) print avf1->side_data->type
Cannot access memory at address 0x0
(gdb) print frames_video1[1]->side_data->type
Cannot access memory at address 0x0
surprisingly, avf1 points to a corrupted frame whose side_data->type is null, which is abnormal. The cause of the issue resides somewhere else.
AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[]
AVFrame *avf1 = &tmp;
You can't do this. I don't know where you learned this, but this is not allowed and fundamentally cannot work. You don't know the size of AVFrame in the application (it is not part of FFmpeg's ABI), so you cannot place a copy on the stack. Instead, do this:
AVFrame *avf1 = frames_video1[k];
Do not ever copy an FFmpeg object on the stack, it will not work. This also means frames_video1[] needs to be an array of AVFrame *, i.e. AVFrame pointers, not an array of AVFrame. If you don't understand why, read about pointers and memory in C and remember again that AVFrame's size is not part of the FFmpeg ABI.
Now, let's debug your object. First, basics of C stack: how many frames are in frames_video1[], and what is k? What is frames_video1[k]->data[0] or frames_video[k]->linesize[0]? Are they legal? Are you sure frames_video1[k] is a legal object? The fact that some copy of non-existing memory is non-NULL means nothing.
Secondly, if the object is legal, what is AVFrame->nb_side_data? You cannot access AVFrame->side_data[] beyond that index.
(gdb) print avf1->side_data->type
You can't do that either. side_data[] is an array of pointers, so instead do this:
(gdb) print avf1->side_data[0]->type
All that said, I again highly recommend you to read up on C pointers and memory allocation, I don't think you entirely understand it. FFmpeg is a very low-level C library and not understanding C will cause lots of grief.

Displaying a byte content given by an address

I have to display the content of n bytes starting in a specific memory address, i.e: an output for 25 bytes since 0x00004000 (segment text in virtual space) would be #include <stdio.h> #inclu (25 letters)
My idea was to assign to a char *c the address given, like: *c=address; and then printf("%s",c);. For me, conceptually makes sense and I know that in some cases it would cause a segmentation fault if the address is not valid.
However I have implemented it and it always causes a segmentation fault. I use pmap <pid> to know what areas can be displayed (low areas) of that process. When I say "areas that can be displayed" I mean text areas (code).
So, what I am doing wrong? is stupid the assignment *c=address; ?
char *c = address;
for (int i = 0; i < n; i++) {
putchar(c[i]);
}
Errors in your code
having something like
char *c;
*c = address;
Is invalid, because c is a dangling pointer (you have never initialized it). You want to set the address which c points to to address: c = address
printf("%s",c);
You don't know if c is a proper string, it may contain garbage or may not be n bytes length. That's why I used putchar
*c = address puts the value of address into the memory c currently points to. That is what the * is doing. To change where c points, use c = address.
But still, this sounds like a rather, ahem, suboptimal programming exercise.

memcpy Seg fault seemingly innoculous

Got a seg fault from my memcpy that gdb can't give me anything else on (at least beyond the simple manner that I know how to use gdb...). This thing is deeply imbedded in some code using the Berkely DB; I have taken out the only lines that should be of any use.
void *databuf;
int smallest;
databuf=malloc(2*sizeof(int));
memset(databuf,0,2*sizeof(int));
/* This next line comes from the DB structures; key.data is a void*... */
smallest=*(int *)key.data;
memcpy(databuf,(void *)smallest,sizeof(int));
To confirm the variable smallest is correct, I can run gdb and get
(gdb) print smallest
$1 = 120321
The error I recieve (in gdb) is the useless
Program received signal SIGSEGV, Segmentation fault.
0x08048efa in main (argc=4, argv=0xbffff344) at index_DB-1.1.c:128
128 memcpy(databuf,(void *)smallest,sizeof(int));
(gdb) backtrace
#0 0x08048efa in main (argc=4, argv=0xbffff344) at index_DB-1.1.c:128
The reason I am doing this is mostly because I am bastardizing the Berkley DB tutorial, but also later I want to do
memcpy(databuf+len,(void *)largest,sizeof(int));
i.e. have a void pointer databuf with first byes the smallest integer and second bytes the largest integer. What am I missing?
In this step, you are interpreting the value in smallest as a pointer:
memcpy(databuf,(void *)smallest,sizeof(int));
Since that value is almost certainly not a valid pointer, this is causing your segfault. Instead, you likely want:
memcpy(databuf, &smallest, sizeof smallest);
Unless you need smallest for some other reason though, you can just copy directly from key.data to to databuf:
memcpy(databuf, key.data, sizeof(int));
(void *)smallest
That takes the integer value of smallest and treats it as a pointer. What you meant to do was this:
(void *)&smallest
It's hard to tell what you're doing, considering the code is so awful, but this looks very suspicious:
memcpy(databuf,(void *)smallest,sizeof(int));
I believe smallest contains normal integer data, not a pointer to anything. So why are you dereferencing it? It doesn't point to anything.
You might want:
memcpy(databuf,(void *) &smallest,sizeof(int));
Also, this is suspect:
smallest=*(int *)key.data;
Is smallest guaranteed to be integer aligned?

can not access memory when accessing pointer to a struct GDB error

I have run gdb, as my code show segfault. I understand that the code that give the error is
210 if (colour_s->colorlist.colorlist_id == 1)
(gdb) print colour_s
$1 = (car_colour_list_t_slot *) 0x21
(gdb) print colorlist
$2 = (car_colour_list_t *) 0x12d1a80
(gdb) print colour_s->colorlist
Cannot access memory at address 0x21
typedef struct {
int colorlist_id;
} car_colour_list_t;
typedef struct _car_colour_list_t_slot {
car_colour_list_t colorlist;
struct _car_colour_list_t_slot *next, *prev;
} car_colour_list_t_slot;
car_colour_list_t_slot *colour_s;
colour_s = (car_colour_list_t_slot *)malloc(sizeof(car_colour_list_t_slot));
car_colour_list_t *colorlist;
colorlist = (car_colour_list_t *)malloc(sizeof(car_colour_list_t));
I have already assigned those pointers memory, but when I tried to print colour_s->colorlist it fails (can not access memory at address 0x21)
Can anyone understand why this happens, although I have already assign memory to each poitner?
Thank you
The colour_s pointer is definitely invalid. There is no doubt about it. GDB is simply informing you of this fact. (Any pointer near 0x0 is invalid, and any pointer with a residue modulo 4 is invalid for your structure.) The malloc function will never return 0x21.
There are lots of ways your program can do this. They boil down to two basic types of errors in your program:
colour_s was not initialized.
colour_s was initialized, but it was accidentally overwritten by an error in a different part of your code.
there is an error in GDB or your compiler (not worth considering)
Run your program with Valgrind or set a watchpoint on colour_s. These will help you discover where the error is in your code.
As an alternative exercise, see if you can find the error just by reading your code, without running it. Read carefully. This kind of exercise will make you a better programmer.

Resources