C - memset segfault for statically allocated char array - c

I get a segfault when trying to memset an array of chars that was allocated statically, but not for an array of the same length that was allocated using malloc.
variable definitions:
//static
char inBuff[IN_BUFF_LEN];
//dynamic
char * inBuffD;
function call:
//static, cast used because char** != char (*) [n]
serverInit(portNum, (char**) &inBuff, &serv_addr, &sockfd)
//dynamic
serverInit(portNum, &inBuffD, &serv_addr, &sockfd)
use within the function:
memset(*inBuffAdr, 0, IN_BUFF_LEN);
I suspect that my problem is in the difference of the function calls, or to be more precise, my incomplete understanding of the "char** != char (*) [n]" situation. But I have been banging at this for too long and can't see the forest from the trees so any hints and advice would be very appreciated.

Just send inBuff (not **inBuff) and then memset inBuffAdr and not *inBufAdr (your other memset is probably not working either, you just don't know it yet)

Why do you need to pass a double-pointer to your serverInit() function? If the function can modify where the pointer points to, then you can't pass a statically allocated array. If the function can't modify where the pointer points to, then you don't need a double-pointer.
The type of &inBuff is pointer to array of char of size IN_BUFF_LEN, which is quite distinct from a char **. You've bludgeoned the compiler into not complaining, claiming that you know better than the compiler what you're doing. Don't use a cast like that unless you are sure you do know more than the compiler.
Frankly, given the current prototype, you'd probably be best off with:
//static
char inBuff[IN_BUFF_LEN];
char *inBuffS = inBuff;
//dynamic
char *inBuffD;
serverInit(portNum, &inBuffS, &serv_addr, &sockfd);
However, I'm deeply suspicious that you should revise serverInit() to take a simple char * instead of char ** for the second argument.

Why not define serverInit() the following way:
serverInit(...., char * inBuff, ....)
then call it
serverInit(...., inBuff, ....)
and then inside serverInit() call memset() like this:
memset(inBuff, 0, IN_BUFF_LEN);

Part of your confusion is in thinking that &inBuff can be dereferenced to get inBuff. If you run this simple test program:
#include <stdio.h>
char inBuff[1000];
int main( int argc, char *argv[])
{
printf( "%p %p\n", inBuff, &inBuff);
return 0;
}
You'll see that it prints the same address for both notations. If you try to dereference &inBuff, you'll be taking the first few bytes of the array as an address.
As others have stated, you should just be passing a pointer to the memory you're going to set. Hopefully this answer will help you with future debugging sessions.

Related

WHY I got seg fault here? need help. Want to put integer into char pointer array

#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 1;
char* test[8];
sprintf(test[0],"%d",num);
printf("%s\n",test[0]);
}
char *test[8] is an array of 8 char *, or pointers to strings, and since you don't specify, they're all set to garbage values. So sprintf is trying to write data to who-knows-where.
You should use char test[8] instead, which allocates an array of 8 char, and then sprintf(test, "%d", num);.
UPDATE: If you want to use char * pointers, you should allocate space:
char *test = malloc(8 /* see note below */);
sprintf(test, "%d", num);
If you want to use an array of char * pointers, it works the same:
char *test[8]; // 8 pointers to strings
test[0] = malloc(8); // allocate memory for the first pointer
sprintf(test[0], "%d", num);
Keep in mind you would have to call malloc for each of test[0] through test[7] individually.
Also, as mentioned in the comments, if your compiler supports it you should use snprintf(). It's like sprintf but it takes an extra parameter which is the size of the buffer:
snprintf(test, 8, "%d", num);
and guarantees not to use more space than you allow it. It's safer, and if you need to, snprintf returns the amount of space it actually wanted, so if you gave it too little room you can realloc and try again.
Note: some will say this should be malloc(8 * sizeof(char)) (or sizeof *test). They are wrong (in my objectively-correct opinion; note the sarcasm)! sizeof(char) is guaranteed to be 1, so this multiplication is unnecessary.
Some advocate the usage of TYPE *p = malloc(x * sizeof *p) so that if TYPE changes, you'll only need to change it in one place, and sizeof *p will adapt. I am one of these people, but in my opinion you will rarely need to upgrade a char * to another type. Since so many functions use char * and would need to be changed in such an upgrade, I'm not worried about making malloc lines more flexible.
sprintf() does not allocate space for the string; you must do that yourself beforehand.
Look at your warnings:
test.c: In function ‘main’:
test.c:8: warning: ‘test[0]’ is used uninitialized in this function
You allocate an array of 8 pointers, but use one without initializing it. You must call malloc and store the result in test[0] before you can write to the memory pointed to by test[0]. You free it at the end.
A useful function, present in GNU and BSD, is asprintf, which will call malloc for you to allocate enough memory for the formatted string:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int num = 1;
char* test[8];
asprintf(&test[0],"%d",num);
printf("%s\n",test[0]);
free(test[0]);
return 0;
}
(Note that you pass the address of your pointer to asprintf — since your pointer is test[0], its address is &test[0].)
You did allocate space but you you are passing the wrong thing. Try this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 1;
char test[8];
sprintf(test,"%d",num);
printf("%s\n",test);
}
int main()
{
char *str[5];
sprintf(str[0], "%d",55);
printf("%s\n",str[0]);
return 0;
}
This will be work. But, if you specify variable instead of integer constant value show the segmentation fault will be occur. This error will be happened at the time of sprintf function execution. Because user space memory access.

what is causing this segmentation fault? example from book

I am going through a book and I tried running this example but I receive a segmentation fault - gdb says it's when it sets argv[0] = filename;
this code is copied/pasted straight from book's downloadable code samples.
#include <unistd.h>
int main() {
char filename[] = "/bin/sh\x00";
char **argv, **envp; // arrays that contain char pointers
argv[0] = filename; // only argument is filename - segmentation fault here
argv[1] = 0; // null terminate the argument array
envp[0] = 0; // null terminate the environment array
execve(filename, argv, envp);
}
Edit: The book is Hacking: The Art of Exploitation by Jon Erickson, which has VERY good reviews. This specific example is used as the first tutorial on converting C into machine code in the shellcode section, specifically it is exec_shell.c and can be downloaded from http://nostarch.com/hacking2/htm . I imagine some context around the use of this code was necessary in order to avoid some of the negative comments below, sorry for leaving details out, and thanks for the help.
It obviously isn’t a very good book. The problem is that neither argv nor envp are initialized, so when you write to argv[0], you’re trying to overwrite some random location in memory.
Try something like this:
#include <unistd.h>
int main() {
char *filename = "/bin/sh";
char *argv[2], *envp[1];
argv[0] = filename;
argv[1] = 0;
envp[0] = 0;
execve(filename, argv, envp);
}
This alternative initializes argv and envp on the stack, with enough space to contain two pointers and one pointer respectively.
In the code above, I’ve made one additional change to repair an additional common (but, in this case, harmless) misunderstanding. The \x00 that was at the end of "/bin/sh\x00" is redundant, since in C static strings are implicitly null-terminated. "/bin/sh\x00" is a string terminated by two nulls.
Alternatively, as pointed out by caf, here is a more compact example with exactly equivalent meaning:
#include <unistd.h>
int main() {
char *filename = "/bin/sh";
char *argv[2] = { filename, 0 };
char *envp[1] = { 0 };
execve(filename, argv, envp);
}
You never allocate the "arrays of pointers" meant to go in argv and envp! What book is it, that omits such crucial steps?!
Either add argv = malloc(2 * sizeof(char*)) (and similarly for envp) before you start assigning to argv[0] and friends, or change argv's and envp's declarations to be arrays of pointers rather than pointers to pointers (the latter's quite a feasible approach, in this specific case, since you do know exactly how many pointers you need in each at the time you're writing the code -- dynamic allocation is therefore somewhat supererogatory;-).
char **argv
argv is pointing to a memory location which you are not allowed to access/write to. It is something that is better known as a wild pointer.
Looks like you need to get a better book! In this code argv is a pointer with no storage allocated to it and pointing at random memory (or probably NULL). When you dereference it with argv[0] = ..., your code ends up trying to write to random memory. Your variable declaration should be something more like:
char *argv[3], *envp[1];
I have no idea where did you get this book, but it obviously sucks. argv is an uninitialized pointer, it holds a random address. Hence accessing it will most probably lead to the access violation.
Before using such multi-level pointers, I recommend reading up on dynamic memmory allocation in C.
Whenever you use pointers, you must also think whether you need to allocate space for the data that the pointers are going to point to (as also the pointers themselves, for multi-level pointers).
For example,
char **bar;
here, bar allocates space for 1 pointer-to-pointer, ie. enough space to store one address. This is not very useful without any additional data allocation.
In reality, you should be doing:
char **bar = calloc( 2 , sizeof(char *) );
here, bar allocates space for 1 pointer-to-pointer, ie. again, space to store one address as bar, AND 2 consecutive locations for storing 2 more pointers, namely bar[0] & bar1.
char bar[0]= calloc( 10 , sizeof(char) );
here, bar[0] allocates space for storing a string of size 10 - 1 (for \0 at end).
Now, if you do a string copy:
strcpy(bar[0],"Hello!");
the final memory map comes to: (addresses in circles, contents in blocks)
Many of the people here are on the right track, but missing some of the numerous problems here.
#include <unistd.h>
int main() {
char filename[] = "/bin/sh\x00";
char **argv, **envp; // arrays that contain char pointers
argv[0] = filename; // only argument is filename - segmentation fault here
argv[1] = 0; // null terminate the argument array
envp[0] = 0; // null terminate the environment array
execve(filename, argv, envp);
}
The problems here are:
1. The pointer array of character strings is never initialized. Pointers take up space too, and thus an array of pointers needs to use malloc in c.
2. Each character pointer in your pointer array needs its own malloc statement before use.
Here is the working code, with printouts to show you what is going on:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
unsigned int i=0;
char filename[] = "/bin/sh\x00";
char **argv; // arrays that contain char pointers
argv=(char **)malloc(sizeof(char*));
argv[0]=(char *)malloc(strlen(filename)*sizeof(char));
strcpy(argv[0],filename);
printf("Arg 0 is %u chars long...\n",strlen(argv[0]));
printf("Arg 0 is ");
while (argv[0][i] != '\0') {
printf("%c",argv[0][i]);
i++;
}
printf("!\n");
free(argv[0]);
}

Is there different about the following memory allocation?

There are four ways to dynamic allocate memory, is there differences among the four ways?
first like this:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
// using 'seq'
}
second like this:
char *seq;
void exam(char *seq){
seq=(char *)malloc(100*sizeof(char));
// using 'seq'
}
third like this:
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
char *change=(char *)malloc(100*sizeof(char));
free(seq);
seq=change;
// using 'seq'
}
fourth like this:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
free(seq);
seq=(char *)malloc(100*sizeof(char));
//using 'seq'
}
and you should konw that, I will use the variable 'seq' outside of the method 'exam'.
please explain the above codes, thank you very much.
Only the first case is valid if you intend to use seq outside of exam.
The other three cases receive the address allocated for seq, but are unable to change it.
To change the value of seq, you need to either return a new value for it, or explicitly modify what's in seq.
You need to investigate Pass by Value to understand why this doesn't work. See this page.
You should not cast the result of malloc() unless you're using an implementation of C that predates the 1989 ANSI standard, or you intend to compile this code as C++, in which case you should be using new instead of malloc(); first of all, it isn't necessary, and second of all, it will mask a compiler diagnostic if you don't have a prototype for malloc() in scope.
Also, sizeof(char) is 1 by definition; using it in this case makes no difference and just adds visual noise.
The canonical form for writing a malloc() statement for any type T is
T *p = malloc(count * sizeof *p);
or
T *p;
...
p = malloc(count * sizeof *p);
Now addressing your four cases...
Your first case is generally correct; you're allocating the memory for seq outside of exam, and passing the pointer by value.
Your remaining cases all have a similar problem; the change to the pointer value seq is not going to be reflected in the caller, and you will have introduced a memory leak. If you're passing a pointer to a function, and you want the pointer value to be overwritten, then you need to pass a pointer to that pointer:
char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }
If you want to resize a dynamically allocated buffer, use realloc():
char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq)
{
char *tmp = realloc(*seq, 100);
if (!tmp)
{
/* realloc failed */
}
else
{
*seq = tmp;
...
}
Note that
char *p = realloc(NULL, 10);
is the same as
char *p = malloc(10);
There are probably many ways to do what your doing. If you intend on using seq outside of the function, the first method you outlined will work.
The other methods you have have other issues if you intend on using seq after calling the function. Since C is pass by value, you are passing the address contained in seq to the routine, which will not change the memory location associated with seq in the last three examples. To change the memory location of seq, you need to pass the address of the pointer into the routine to set the pointer. This is shown in David Cournapeau example.
The issue with the last two cases is that you "freed" the memory, but you are still retaining a pointer to the memory as the value of seq will not be changed and you can use it to access memory you have "freed". This is known a a dangling pointer.
David Cournapeau suggestion of using a function to return the pointer would give you access to the memory you allocated in the function. Otherwise you will need to pass the address of seq into the routine and dereference the value to set it to the allocated space.
It all depends on what you are trying to do. If possible, it is better to do malloc/free in the same scope, IMO, it makes the code much more readable - memory allocation in C is already hard enough. In your case, you would first malloc, call the function, and free after outside the function. But of course, it is not always possible.
Some of your solutions will not work: the second one, for example, will not do what you want, because when you call the function, the pointer is copied:
char *p;
function(p);
void function(char *q) {
// q is a copy of p, so when q is set by malloc, it will not be reflected in p
q = malloc(100);
}
Generally, you should do as the fopen functions: you return a pointer:
char* p function() {
char* ret;
ret = malloc(100);
return ret;
}
char *p = function();
Or you could use a pointer to a pointer:
char *p;
function(&p);
void function(char **q) {
// q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
*q = malloc(100);
}
I think the first one is much better, though, in general.
Also, concerning your style: sizeof(char) is useless, it is always equal to 1 by definition, whatever compiler/platform you are using, and casting the malloc is useless and actually dangerous (because it hides missing header inclusion where malloc is declared). It is only useful if you use malloc in C++ (where the cast is mandatory).
I think these are differences in scope
To cast some light on the situation, consider this rewriting:
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
// using 'var'
}
//--
char *seq;
void exam(char *var){
var=(char *)malloc(100*sizeof(char));
// using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
char *change=(char *)malloc(100*sizeof(char));
free(var);
var=change;
// using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
free(var);
var=(char *)malloc(100*sizeof(char));
//using 'var'
}
When you call
exam(seq);
the above versions are identical to your original.

qsort crashing program - C

Trying to follow this example. (Section String sorting...)
Is there anything obvious that would make this crash in stdlib's qsort.c?
I also tried cstring_cmp with strncmp specifying 30 chars max, much more than I have.
*fileArray[20] seems to be correctly populated with strings.
Thanks.
char* ptr_fileName;
char* fileArray[20];//number of files
size_t strings_len;
ptr_fileName = (char*)malloc((strlen(FindFileData.cFileName)+1)*sizeof(char));
memcpy(ptr_fileName, FindFileData.cFileName, strlen(FindFileData.cFileName)+1);
fileArray[i] = ptr_fileName;
strings_len = sizeof(fileArray) / sizeof(char *);
qsort(fileArray, strings_len, sizeof(char *), cstring_cmp);
//crashing in qsort.c
qsort c-string compare function:
/* qsort C-string comparison function */
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
/* strcmp functions works exactly as expected from
comparison function */
}
You say you are only filling fileArray with 10 strings, leaving 10 entries uninitialized.
When you call qsort, you pass 20 as the strings_len argument.
This will, of course, result in undefined behavior.
You have to give qsort accurate information.
If you are passing 10 strings in the array, you must also pass the number 10 as the number of elements to be sorted.
Note:
If you follow my earlier answer, setting a breakpoint on cstring_cmp, you would quickly see when the compare method is called with invalid data, leading directly to the crash.
How do you populate:
char* fileArray[20];
as it stands, it's an array of uninitialised pointers.
Set a breakpoint in cstring_cmp, and watch as it is called each time.
See if the ultimate crash happens inside cstring_cmp, or in qsort.
Check the state of the fileArray just before the crash.
*fileArray[20] seems to be correctly populated with strings.
The asterisk before fileArray makes me veeeery suspicious about the correctness of the way you populated the array.
I don't observe anything else that might break your code.
As you are not initialising the contents of fileArray, it legal contains random memory, not legal char pointers.

Passing a pointer to a char array to a function

I have a pointer to my char array like this.
unsigned char *recvBuf;
recvBuf = (unsigned char *)malloc(sizeof(char)*RECVBUF);
I then pass that to a function defined as
void setHeader(MyHeader *myHeader, unsigned char *buffer)
Which copies the first 12 bytes into a struct
Then I try and pass it to another function later on
Record readRecord(unsigned char *buffer, int *arrayPosition, int buffsize)
But the program always becomes unresponsive when I try and access any part of the array using [], in the exact same way it was used in the previous functiom. And i'm also fine to access it like that before i pass it to the function.
Ideas would be much appreciated.
Thanks
EDIT:
Pointers are the same.
This is inside the second function
I added this code to the top and it works just fine
int k = *arrayPosition;
printf("%p \n", buffer);
printf("%c \n", buffer[k]);
This is the original code, the program becomes unresponsive adfter i = *arrayposition...
int i, j;
Record *myRecord;
Resource *myResource;
unsigned char name[255];
unsigned char data[50];
unsigned int offset;
i = *arrayPosition;
while(buffer[i] != '\0')
{
if((buffer[i] & 0xC000) == 0xC000)
{
Really need more context to assist here, there's nothing obviously untoward from what you've said.
Basics:
Check that you haven't indexed off
the end of your memory block.
Check that you're not passing
&recvBuf where you mean to pass
recvBuf? A compiler should
catch this, but you'd trash your stack if you did this, maybe using a cast.
Input is not enough to be sure of the problem that makes the pointer go bad but a good catch would be to check with gdb if the pointer changes between the function call you descripted.
Do you modify any char of the array? You should dereference the pointer with * in that case.
If you cannot use the pointer after the call causes can be:
it is changed erroneously inside the function
it is a pointer to an allocated value in the stack that is deallocated implicitly somewhere (but it sounds strange)

Resources