I don't understant how I can call this function correctly in main.
I tried calling like this: X *p1=malloc(sizeof(X));read(&p1);
struct x
{ int c;
char n[250];
char u[150];
};
typedef struct x X;
void myread(X *p);
void myread(X *p)
{
scanf("%d",&p->c);
fgets(p->n,sizeof(p->n),stdin);
fgets(p->u,sizeof(p->u),stdin);
}
void main(){
X *p1;
p1=malloc(sizeof(X));
myread(p1);
}
The function as declared in your question (void read(X *p)) needs a pointer to X as parameter.
Your declaration of (X *p1) ensures that it is a pointer to X.
Your initialisation (p1=malloc(sizeof(X));) makes it a pointer to a suitably sized piece of useable memory.
That's it.
You then however use that appropriate pointer with the "take the address operator" &, which results in a pointer-to-pointer to X.
Calling the function with p1 as parameter would look like
read(p1);
I.e. just give the pointer to X as it is.
The function looks like it is supposed to fill the malloced space with values.
How that works and how it could be improved is not part of your question.
Don't use gets. It is dangerous and obsolete. Use fgets instead. Replace gets(p->n) with fgets(p->n, sizeof(p->n), stdin); and so on.
Don't name your function read (since that is the name of a POSIX standard function). Replace it by another name, e.g. myread.
You probably want to do:
X *p1=malloc(sizeof(X));
in your main. Then, you need to check that malloc succeeded:
if (!p1) { perror("malloc p1"); exit(EXIT_FAILURE); }
Beware that malloc gives (on success) some uninitialized memory zone. You may want to clear it using memset(p1, 0, sizeof(p1)), or you could use p1 = calloc(1, sizeof(X)) instead.
At last you can pass it to your myread:
myread(p1);
Don't forget to call free(p1) (e.g. near the end of your main) to avoid a memory leak.
Learn to use valgrind, it catches many memory related bugs.
Of course you need to carefully read the documentation of every standard function that you use. For example, fgets(3) documents that you need to #include <stdio.h>, and that call to fgets can fail (and your code needs to check that, see also errno(3) & perror(3)...). Likewise, malloc(3) wants #include <stdlib.h> and should be checked. And scanf(3) can fail too, and needs to be checked.
You should compile with all warnings and debug info (gcc -Wall -Wextra -g with GCC), improve your code to get no warnings, and you should use the gdb debugger; you may want to use GCC sanitizers (e.g. instrumentation options like -fsanitize=address, -fsanitize=undefined and others),
Beware of undefined behavior (UB). It is really scary.
PS. I hope that you are using Linux with gcc, since it is a very developer friendly system. If not, adapt my answer to your operating system and compiler and debugging tools.
Related
For debugging purposes, I would like malloc to return the same addresses every time the program is executed, however in MSVC this is not the case.
For example:
#include <stdlib.h>
#include <stdio.h>
int main() {
int test = 5;
printf("Stack: %p\n", &test);
printf("Heap: %p\n", malloc(4));
return 0;
}
Compiling with cygwin's gcc, I get the same Stack address and Heap address everytime, while compiling with MSVC with aslr off...
cl t.c /link /DYNAMICBASE:NO /NXCOMPAT:NO
...I get the same Stack address every time, but the Heap address changes.
I have already tried adding the registry value HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\MoveImages but it does not work.
Both the stack address and the pointer returned by malloc() may be different every time. As a matter of fact both differ when the program is compiled and run on Mac/OS multiple times.
The compiler and/or the OS may cause this behavior to try and make it more difficult to exploit software flaws. There might be a way to prevent this in some cases, but if your goal is to replay the same series of malloc() addresses, other factors may change the addresses, such as time sensitive behaviors, file system side effects, not to mention non-deterministic thread behavior. You should try and avoid relying on this for your tests.
Note also that &test should be cast as (void *) as %p expects a void pointer, which is not guaranteed to have the same representation as int *.
It turns out that you may not be able to obtain deterministic behaviour from the MSVC runtime libraries. Both the debug and the production versions of the C/C++ runtime libraries end up calling a function named _malloc_base(), which in turn calls the Win32 API function HeapAlloc(). Unfortunately, neither HeapAlloc() nor the function that provides its heap, HeapCreate(), document a flag or other way to obtain deterministic behaviour.
You could roll up your own allocation scheme on top of VirtualAlloc(), as suggested by #Enosh_Cohen, but then you'd loose the debug functionality offered by the MSVC allocation functions.
Diomidis' answer suggests making a new malloc on top of VirtualAlloc, so I did that. It turned out to be somewhat challenging because VirtualAlloc itself is not deterministic, so I'm documenting the procedure I used.
First, grab Doug Lea's malloc. (The ftp link to the source is broken; use this http alternative.)
Then, replace the win32mmap function with this (hereby placed into the public domain, just like Doug Lea's malloc itself):
static void* win32mmap(size_t size) {
/* Where to ask for the next address from VirtualAlloc. */
static char *next_address = (char*)(0x1000000);
/* Return value from VirtualAlloc. */
void *ptr = 0;
/* Number of calls to VirtualAlloc we have made. */
int tries = 0;
while (!ptr && tries < 100) {
ptr = VirtualAlloc(next_address, size,
MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
if (!ptr) {
/* Perhaps the requested address is already in use. Try again
* after moving the pointer. */
next_address += 0x1000000;
tries++;
}
else {
/* Advance the request boundary. */
next_address += size;
}
}
/* Either we got a non-NULL result, or we exceeded the retry limit
* and are going to return MFAIL. */
return (ptr != 0)? ptr: MFAIL;
}
Now compile and link the resulting malloc.c with your program, thereby overriding the MSVCRT allocator.
With this, I now get consistent malloc addresses.
But beware:
The exact address I used, 0x1000000, was chosen by enumerating my address space using VirtualQuery to look for a large, consistently available hole. The address space layout appears to have some unavoidable non-determinism even with ASLR disabled. You may have to adjust the value.
I confirmed this works, in my particular circumstances, to get the same addresses during 100 sequential runs. That's good enough for the debugging I want to do, but the values might change after enough iterations, or after rebooting, etc.
This modification should not be used in production code, only for debugging. The retry limit is a hack, and I've done nothing to track when the heap shrinks.
I was trying to understand the working of free.
Is it defined in the standards that free() will not change the pointer which it was passed?
In standard C argument passing is by value. So a function cannot change the value of its argument (and this is not specific to free). Every call is a call by value. If inside a function you change some argument only a local copy (e.g. in some machine register) of that argument is changed and the caller does not see any change.
If you want to change something, you'll pass the address of that something as a value and you'll dereference that pointer.
Hence free won't change the pointer you pass to it, but you need to be sure to never use that pointer again. Otherwise, that is undefined behavior. A common style is to code free(ptr), ptr=NULL; (so that any further access thru ptr would crash with a segmentation fault).
In practice, most implementations of the C standard library are marking a free-d zone to be reusable by future malloc. But sometimes (notably when freeing a large memory zone) the memory is released to the kernel (e.g. by munmap(2) on Linux). What really happens to the memory zone is implementation specific.
Read wikipages of C dynamic memory allocation & virtual address space.
Look also inside the source code of some free software C standard library implementation (e.g. most libc on Linux, such as musl-libc or GNU libc...). Compile your code with all warnings & debug info (e.g. gcc -Wall -Wextra -g if using GCC...) then use valgrind to hunt memory leak bugs.
The const storage type tells the compiler that you do not intend to modify a block of memory once allocated (dynamically, or statically). Freeing memory is modifying it.
Whether free changes the input argument or not relevant to the calling code. The calling code still has the pointer. It is similar to passing an int to a function. The called function may change the variable but it is change of the copy, not the original.
void foo(int i)
{
i += 2;
}
void bar()
{
int i = 10;
foo(i);
}
Here, the change made to i in foo does not change the value of i in `bar.
Similarly,
void free(void* ptr)
{
// Do the needful to deallocate
...
ptr = NULL;
}
void test()
{
char* p = malloc(10);
...
free(p);
}
Here, the change made to ptr in free does not change the value of the pointer in test. Hence, it does not make much sense to make the argument of free to be of type void* const.
Since there is an option -fstack-protector-strong in gcc to detect stack smashing. However, it can not always detect stack buffer overflow. For the first function func, when I input a 10 char more string, the program does not always crash. My question is where there is a way to detect stack buffer overflow.
void func()
{
char array[10];
gets(array);
}
void func2()
{
char buffer[10];
int n = sprintf(buffer, "%s", "abcdefghpapeas");
printf("aaaa [%d], [%s]\n", n, buffer);
}
int main ()
{
func();
func2();
}
Overflows on the stack are either hard to detect or very expensive to detect - chose your poison.
In a nutshell, when you have this:
char a,b;
char *ptr=&a;
ptr[1] = 0;
then this is technically legal: There is space allocated on the stack which belongs to the function. It's just very dangerous.
So the solution might be to add a gap between a and b and fill that with a pattern. But, well, some people actually write code as above. So your compiler needs to detect that.
Alternatively, we could create a bit-map of all bytes that your code has really allocated and then instrument all the code to check against this map. Very safe, pretty slow, bloats your memory usage. On the positive side, there are tools to help with this (like Valgrind).
See where I'm going?
Conclusion: In C, there is no good way to automatically detect many memory problems because the language and the API is often too sloppy. The solution is to move code into helper functions that check their parameters rigorously, always to the right thing and have good unit test coverage.
Always use snprintf() versions of functions if you have a choice. If old code uses the unsafe versions, change it.
You can use a tool called Valgrind
http://valgrind.org/
My question is where there is a way to detect stack buffer overflow...
void func()
{
char array[10];
gets(array);
}
void func2()
{
char buffer[10];
int n = sprintf(buffer, "%s", "abcdefghpapeas");
printf("aaaa [%d], [%s]\n", n, buffer);
}
Because you are using GCC, you can use FORTIFY_SOURCES.
FORTIFY_SOURCE uses "safer" variants of high risk functions like memcpy, strcpy and gets. The compiler uses the safer variants when it can deduce the destination buffer size. If the copy would exceed the destination buffer size, then the program calls abort(). If the compiler cannot deduce the destination buffer size, then the "safer" variants are not used.
To disable FORTIFY_SOURCE for testing, you should compile the program with -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0.
The C Standard has "safer" functions via ISO/IEC TR 24731-1, Bounds Checking Interfaces. On conforming platforms, you can simply call gets_s and sprintf_s. They offer consistent behavior (like always ensuring a string is NULL terminated) and consistent return values (like 0 on success or an errno_t).
Unfortunately, gcc and glibc does not conform to the C Standard. Ulrich Drepper (one of the glibc maintainers) called bounds checking interfaces "horribly inefficient BSD crap", and they were never added. Hopefully it will change in the future.
First of all Do Not Use gets. By now almost everyone knows the all the security and reliability problems that can occur with gets. But it's included here for historical reasons as well because it's a very good example of bad programming.
Let's look at all the problems with the code:
// Really bad code
char line[100];
gets(line);
Because gets does not do bounds checking a string longer than 100 characters will overwrite memory. If you're lucky the program will just crash Or it might exhibit strange behavior.
The gets function is so bad that the GNU gcc linker issues a warning whenever it's used.
/tmp/ccI5WJ5m.o(.text+0x24): In function `main':
: warning: the `gets' function is dangerous and should not be used.
Protect array accesses with assert
C/C++ does not do bound checking.
for example:
int data[10]
i = 20
data[20] = 100 //Memory Corruption
Use the assert function for above code
#include<assert.h>
int data[10];
i=20
assert((i >= 0) && (i < sizeof(data) / sizeof(data[0]))); // throws
data[i] = 100
Array overflows are one of the most common programming errors and are extremely frustrating to try and locate. This code doesn't eliminate them, but it does cause buggy code to abort early in a way that makes the problem tremendously easier to find.
And use snprintf(buffer, sizeof(buffer), "%s", "abcdefghpapeas") and some tools like valgrind or GDB.
Hope this helps you..
Code:
union foo
{
char c;
int i;
};
void func(void * src)
{
union foo dest;
memcpy(&dest, src, sizeof(union foo)); //here
}
If I call func() like this:
int main()
{
char c;
int i;
func(&c);
func(&i);
return 0;
}
In the call func(&c), the size of c is less than sizeof(union foo), which may be dangerous, right?
Is the line with memcpy correct? And if not, how to fix it?
What I want is a safe call to memcpy that copy a void * pointer to a union.
A little background: this is extracted from a very complicated function, and the signature of func() including the void * parameter is out of my control. Of course the example does nothing useful, that's because I removed all the code that isn't relevant to provide an example with minimum code.
In the call func(&c), the size of c is less than sizeof(union foo), which may be dangerous, right?
Right, this will lead to undefined behaviour. dest will likely contain some bytes from memory areas surrounding c, and which these are depends on the internal workings of the compiler. Of course, as long as you only access dest.c, that shouldn't cause any problems in most cases.
But let me be more specific. According to the C standard, writing dest.c but reading dest.i will always yield undefined behaviour. But most compilers on most platforms will have some well-defined behaviour for those cases as well. So often writing dest.c but reading dest.i makes sense despite what the standard says. In this case, however, reading from dest.i will still be affected by unknown surrounding variables, so it is undefined not only from the standards point of view, but also in a very practical sense.
There also is a rare scenario you should consider: c might be located at the very end of allocated memory pages. (This refers to memory pages allocated from the operating system and eventually the memory management unit (MMU) hardware, not to the block-wise user space allocation done by malloc and friends.) In this case, reading more than that single byte might cause access to unmapped memory, and hence cause a severe error, most likely a program crash. Given the location of your c as an automatic variable in main, this seems unlikely, but I take it that this code snippet is only an example.
Is the line with memcpy correct? And if not, how to fix it?
Depends on what you want to do. As it stands, the code doesn't make too much sense, so I don't know what correct reasonable application you might have in mind. Perhaps you should pass the sizeof the src object to func.
Is the line with memcpy correct? And if not, how to fix it?
you should pass the size of memory pointed by void pointer so you can know src has this much size so you just need to copy this much of data...
Further more to be safe you should calculate the size of destination and based on that you should pass size so illegal access in reading and writing both can be avoided.
The memcpy is fine. By passing the address of the smallest member of the union, you will end with garbage in the larger member. A way to avoid the garbage-bit is to by default make all calls to func - which I assume you do control - use only pointers to the larger member - this can be achieved by setting the larger member to the smaller one: i = c and then call func(&i).
func itself is ok.
The problems lies in whether the caller really makes sure that the memory referenced when calling func() is at least sizeof(union foo).
If the latter is always the case, everything is fine. It is not then case for the two calls to func() in the OP's example.
If the memory referenced when calling func() is less then sizeof(union foo) then memcpy() provokes undefined behaviour.
Since you know what and what size to copy, why not give a more explicit function, let the function know how to copy the right size of memory which void pointer pointed to.
union foo
{
char c;
int i;
};
void func(void * src, const char * type)
{
union foo dest;
if(strcmp(type, "char") == 0){
memcpy(&dest, src, 1);
}else if(...){
}
}
Where is this behaviour documented (if it is at all)?
When you declare a pointer in C in the middle of a block, it will probably be in a wrong state (pointing to unusable memory) and you cannot use the standard if (a) free(a) for freeing it.
The simplest program that comes to mind is
#include <stdlib.h>
int main(int argc, char *argv[]){
if(argc > 1) goto END;
char *a = NULL;
a = calloc(1,1);
END:
if(a) free(a);
}
Run the program without parameters and it works OK, if you run it with at least one parameter, it will probably break as follows:
suprisingly (to me), if you compile it with clang, it may work (on my OS X it does, but on a NetBSD it does not). If you do with gcc, it always returns a
malloc: *** error for object 0x7fff5fc01052: pointer being freed was not allocated
Notice that the same program with the declaration at the head of the block is correct.
Edit: Notice that the question is about documentation. I realize doing what I describe is unsafe but I have found no place where it is explicitly shown.
The "pattern"
if(a) free(a);
is certainly not standard, or at least it shouldn't be. It's safe to pass NULL to free(), so the if adds nothing.
I would expect the value of a to be undefined (not likely to be NULL) if you jump past the initialization, which makes perfect sense to me. This is really hairy code, don't do this.
It could be argued that the existance of the goto and label imply a scope that isn't implemented, and there's no reason at all that the free(a); statement is after the label (outside the "invisible" scope where a is defined).