ASAN heap use after free - c

I am running ASAN for finding memory leaks in a very big project. I have found out the cause, but do not know how to resolve it. I have made a sample program to make the problem understandable.
In the below program I can only work-around on specified code. For rest of the code it is not possible to do work around.
So please suggest what work around I may have to resolve below ASAN error.
(How to make pointer two as NULL using t1?)
#include<stdio.h>
#include<stdlib.h>
typedef struct l
{
int a, b;
}pack;
void delete_me(pack *ap)
{
free(ap);
}
int main(void)
{
pack **d_ptr = (pack **)malloc(3 * sizeof(pack *));
pack *one, *two, *three;
one = (pack *)malloc(sizeof(pack));
one->a = 1, one->b = 2;
two = (pack *)malloc(sizeof(pack));
two->a = 3, two->b = 4;
three = (pack *)malloc(sizeof(pack));
three->a = 5, three->b = 6;
d_ptr[0] = one;
d_ptr[1] = two;
d_ptr[2] = three;
// I can Only work-around below code (4 lines)
pack *t1 = d_ptr[1]; // For which index t1 would be assigned, is not known before hand
t1->a = 1; t1->b = 2;
printf("a: %d, b: %d\n", two->a, two->b);
delete_me(t1); // How to delete t1 so that corresponding pointer also becomes NULL?
// Work around only till here was possible.
// Below this, No workaround possible.
if (two && (two->a == one->a)) // ASAN ERROR
printf("ERROR\n");
else
printf("It works!\n");
return 0;
}
ASAN Error:
ERROR: AddressSanitizer: heap-use-after-free

Unfortunately your problem isn't really solvable.
When you have multiple copies of the same pointer, e.g.
int *p1 = malloc(sizeof (int));
int *p2 = p1;
int *p3 = p2;
then freeing any of them invalidates all of them:
free(p2);
// Now p1, p2, p3 have invalid values.
// The C standard calls these "indeterminate values"; accessing them has undefined behavior
You can manually set p2 to NULL after freeing, but that still leaves p1 and p3 dangling. You cannot automatically find all copies of a pointer value that may exist anywhere in your program's memory.
You need to restructure the logic of your program. There is no quick and easy fix.

Related

Why can't I realloc an array that was fully initialized?

Have a look at the piece of code below. When I create an array by mallocating space for it I can always resize the array without loss of data. But when I create an array by fully initializing it with int test2[] = {3}; I am unable to realloc. Why is that? This is just a silly example but it presents the problem I am facing well.
I tried referencing test2 in different ways (*, &, **, etc) but at some point I found myself just hoping to magically find the solution without knowing what I was doing anymore.
I have been googling a lot but I cannot seem to find a proper explanation for this or solution that works.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *test1 = malloc(1 * sizeof(int));
test1[0] = 1;
test1 = realloc(test1, 2 * sizeof(int));
test1[1] = 2;
for(int i = 0; i < 2; i++)
{
printf("%d\n", test1[i]);
}
int test2[] = {3};
test2 = realloc(test2, 2 * sizeof(int));
test2[1] = 4;
for(int i = 0; i < 2; i++)
{
printf("%d\n", test2[i]);
}
}
Output:
test.c: In function 'main':
test.c:17:8: error: assignment to expression with array type
test2 = realloc(test2, 2 * sizeof(int));
When I remove the code after the first for loop, the program compiles and executes nicely as it should.
The declaration int test2[] = {3}; does not create memory that can be later either freed or re-allocated! Rather, it defines an array of fixed length, most likely 'created' on the stack.
A call to malloc, on the other hand, allocates the requested amount of memory from the heap (essentially, a large pool of memory available to your running program); this memory 'chunk' can later be re-sized with realloc and must be released (when you're done with it) by calling free.

memory allocation in C for pointers

I'm trying to build a structure called PROCESS in C, this struct should contain the ID(id) and waiting time (wt) of the process.
typedef struct PROC{
int id;
int wt;
}PROCESS;
PROCESS *pt = NULL;
Now I want to make more then one instance of this struct like an array.
what I want to do is something like this':
PROCESS pt[10];
pt[0].id = 5;
pt[1].id = 7;
But I want to do it using dynamic memory allocation:
pt = calloc(2,sizeof(PROCESS));
pt[0]->id = 5;
What is my mistake?
pt is a pointer to PROCESS, pt[0] is the first PROCESS object pointed to by pt.
The -> operator to access members of a struct must be used with pointers only, otherwise use .
pt[0].id = 5;
would be correct.1
An since you say you are doing C, you don't need to cast malloc or calloc.
PROCESS *pt = calloc(2, sizeof *pt);
if(pt == NULL)
{
// errror handling
// do not continue
}
pt[0].id = 5;
pt[1].id = 7;
Also don't forget to check the return value of calloc and don't forget to free
the memory later with free(pt);.
Fotenotes
1Note that this would be equivalent to
pt->id = 5;
but if you want to set id of the second element, you would need to do
(pt+1)->id = 7;
but I think it's more readable to do
pt[1].id = 7;
typedef struct process{
int id;
int wt;
}processes;
I would allocate like this->
int numberOfDynamicStructs=2;
processes* myProcesses= calloc(numberOfDynamicStructs,sizeof(processes));
Write->
myProcesses[0].id=1;
myProcesses[1].id=2;
Read->
printf("%d %d",myProcesses[0].id,myProcesses[1].id);
Free when done..
/A

Allocating memory for structs, 2 different ways?

I am new in C, but not new in programming. Is there a difference between the 2 sets of codes ? If there is not, is there a convention on which one to prefer ? Is there a performance difference ?
typedef struct
{
int x;
int y;
} something_t;
-
something_t* s;
s = malloc(sizeof(int)*2);
s->x = 1;
s->y = 1;
or
something_t* s;
s->x = 1;
s->y = 1;
The good way to do it is
something_t *something;
something = malloc(sizeof(*something));
if (something == NULL)
please_do_not_use_something_perhaps_return_NULL_or_quit();
something->x = 2;
something->y = 2;
This way, you ensure the size is right and the code is more maintainable. And you also prevent a disaster by checking that malloc() didn't return NULL giving you chance to do something about it. Assuming no-errors is wrong all the time, in this because you never know when the system will run out of RAM.
Your second example doesn't work, this
something_t *something;
something->x = 2;
something->y = 2;
Invokes Undefined Behavior, one of the possible outcomes is that it "Works". So you might think that it worked because of undefined behavior, but the truth is, it's wrong.
In this case something doesn't point to valid memory, so you don't know for sure what the value of something is and it can be anything, thus the behavior of such program is unpredictable.
Also, read why you should avoid _t as a suffix for type names.
To my understanding, the first version should be
something_t* s;
s = malloc(sizeof(something_t));
s->x = 1;
s->y = 1;
instead of manually fiddling with the size of individual members; the second versions performs no allocation at all and accesses uninitialized memory.
something_t* s;
does not allocate any memory for your structure, it only allocates a pointer (to a random memory area). It is very likely it will trigger a segmentation fault when you try to read/write to it.
The good way to allocate your memory is
something_t* s;
s = malloc(sizeof(something_t));
or the one-liner
something_t* s = malloc(sizeof(something_t));
Don't forget to use free(s); when you're done with it.
If you want stack-allocation, you can use :
something_t s;
s.x = 2;
s.y = 2;

Using C Dynamic allocation using malloc and realloc

I am having some trouble using the malloc and realloc functions in C and saving values in them using 2 seperate functions
Note i have only recently just started using c and porbably there are multiple bugs in the code but my main focus is saving the values to the struct
i need to be able to save multiple values to a single array.
these are my functions
int ArrayCreate() {
int *pt;
pt = (ASet *)calloc(1,sizeof(ASet));
pt == NULL;
return *pt;
}
//possible 2nd *
void ArrayAdd(ASet **arrayStruct, int x) {
ASet *pt = NULL;
*arrayStruct=realloc(*arrayStruct,1*sizeof(ASet));
pt = arrayStruct;
*arrayStruct->value = x;
free(pt);
}
and in my main i have
ASet *arr_pt = NULL;
to create an array
printf("a new array is created \n");
arr_pt = ArrayCreate();
break;
to add something to an array
printf("Enter integer \n");
scanf("%d",&x);
ArrayAdd(arr_pt,x);
while (getchar() != '\n') {
continue;
}
break;
also to test i have added this but i am not sure about it
void ArrayShow(ASet *arrayStruct) {
ASet *pt = arrayStruct;
//printf("%d \n", pt[0].value);
printf("%d \n", pt[1].value);
printf("%d \n", pt[2].value);
printf("%d \n", pt[3].value);
printf("%d \n", pt[4].value);
}
i only need to know how to save correctly using realloc and calloc but for some reason the pt[0] is ignored and anything after p[1] is garbage
simple sample
#include <stdio.h>
#include <stdlib.h>
typedef int Item;
#define PRN_Item "%d"
typedef struct da {
size_t size;
Item *value;
} ASet;
ASet *ArrayCreate(void){
return calloc(1, sizeof(ASet));
}
void ArrayAdd(ASet *arrayStruct, Item x){
ASet *ap = arrayStruct;
Item *p = ap->value;
p = realloc(p, (ap->size + 1)*sizeof(Item));
if(p){
ap->value = p;
ap->value[ap->size] = x;
ap->size += 1;
} else {
perror("realloc");
exit(1);
}
}
void ArrayShow(ASet *arrayStruct) {
Item *v = arrayStruct->value;
size_t n = arrayStruct->size;
while(n--){
printf(PRN_Item " \n", *v++);
}
}
void ArrayDrop(ASet *arrayStruct){
free(arrayStruct->value);
free(arrayStruct);
}
int main(){
ASet *arr_pt = ArrayCreate();
if(!arr_pt){
perror("ArrayCreate");
exit(1);
}
printf("a new array is created \n");
while(1){
int x;
printf("Enter integer \n");
if(1!=scanf("%d", &x))
break;
ArrayAdd(arr_pt, x);
}
ArrayShow(arr_pt);
ArrayDrop(arr_pt);
return 0;
}
EDIT:
The line below is a comment so it's not executed:
//printf("%d \n", pt[0].value);
And your casting to pt with the wrong type that's why you're getting garbage
/* replace Aset with int and SIZE must be a defined size */
pt= calloc(SIZE, sizeof(int));
pt == NULL is a comparaison expression not an assingment statment:
pt = NULL // assining NULL to pt
ArrayCreate must return a pointer to the fisrt element of the array, not the value of the address pointed to:
int *ArrayCreate() {
int *pt;
pt = calloc(SIZE,sizeof(int));
pt == NULL;
return pt;
}
there are a few things wrong with your code here are some:
instead of pt == NULL; you should do pt = NULL because using the first compares between pt and NULL and doesn't assign NULL to pt
this pt = arrayStruct is illegal because pt is of type ASet while arrayStruct is of type **ASet you should replace it with pt = *arrayStruct
here *arrayStruct->value = x; it's like you're asking for the address of the member value to be changed to x you should instead do *(arrayStruct)->value = x;
Problems:
There's no visible record of how big the array is, so you can't tell what size to reallocate.
Your ArrayCreate() function should return a pointer to the structure. The pt == NULL; statement does nothing; your compiler should be warning you about a statement with no effect. Because you are returning an int and not a pointer, you are leaking memory.
Your ArrayAdd() function doesn't know how much space to allocate (point 1 again). The code should not be using free(pt); realloc() may have returned a pointer to the same location or to a different location, but either way, it has dealt with the old memory.
I did not understand the 1, 2; so you're saying pt should be *pt? What effect will that have and 3 the part about how much space?
Consider the ArrayCreate() function — as currently written:
int ArrayCreate() {
int *pt;
pt = (ASet *)calloc(1,sizeof(ASet));
pt == NULL;
return *pt;
}
First of all, the code is confused about whether it is dealing with int or ASet types. It appears to be allocating an array with 1 (zeroed) ASet element but assigning that to an int *. The next line should probably be an if statement. The code should probably read:
ASet *ArrayCreate(void)
{
ASet *pt = (ASet *)calloc(1, sizeof(ASet));
if (pt == NULL)
{
fprintf(stderr, "Memory allocation failed!\n");
exit(1);
}
return pt;
}
I don't object to the cast on the return from calloc() as long as you reassure me that you always compile with options such that if you forget to include <stdlib.h>, your code will not compile. For example, I mainly use GCC and always compile with options such as:
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror ...
If you don't compile like that, then you're better off omitting the cast. As you'll notice, there are others who are not as flexible about the issue of casting the return from malloc() et al. (I even use those options on other people's code on SO; it is sometimes painful getting their code to compile cleanly.)
The error handling or memory allocation is about the simplest available option — report the error (on standard error, be it noted) and exit. You can be as creative as you like about how to handle the error, but failing fast has many merits in many situations.
Now, the code I've shown is more or less coherent, but the only way you know that there's one element in the array of ASet values is ... because it was just created with one element.
When you call ArrayAdd() the first time, you can assume that there was one element in the array, but when you call it another time, you have no idea how many rows are in the array, so you'll still allocate 2 elements to the array, even though that's a no-op. You need to know, somehow, how many elements are already in the array.
As currently written:
void ArrayAdd(ASet **arrayStruct, int x) {
ASet *pt = NULL;
*arrayStruct=realloc(*arrayStruct,1*sizeof(ASet));
pt = arrayStruct;
*arrayStruct->value = x;
free(pt);
}
You take the (pointer to the) array that you're passed, and resize the array to one element. The pt = arrayStruct; line should generate compilation warnings; you're assigning an ASet ** to an ASet *; they're very different types. The free(pt) is simply wrong — irredeemably wrong. You need code something like:
void ArrayAdd(ASet **arrayStruct, size_t new_size, int x)
{
ASet *pt = realloc(*arrayStruct, new_size * sizeof(ASet));
if (pt == 0)
{
fprintf(stderr, "Memory allocation failed!\n");
exit(1);
}
pt[new_size-1].value = x;
*arrayStruct = pt;
}
Again the code fails fast on memory allocation failure. It is careful not to clobber *arrayStruct before it knows that it is safe to do so. It assigns x to the value member of the last element of the array. Note that realloc() does not zero the extra memory it makes available. The code also does not know how big the array was before; it can't tell whether the array is growing or shrinking — only the calling code is privy to that information.
So, this isn't a very good bit of code, but it is better than what was there before.

How to initialize the structure member with using pointer?

I have below code. In below code the value 5 gets stored in variable a(i.e abc.a). But I would like to intialize the value in c (i.e abc.c). How to do that? My requirement is to fill the data for c not for a.
typedef struct abc
{
int a;
int b;
int c;
}abc;
typedef struct def{
int *ptr;
abc strpt;
}def;
typedef struct xyz{
int *pointer;
}xyz;
int main()
{
int *temp, tmp;
abc* ab;
tmp = 5;
temp = &tmp;
ab = (abc*)malloc(sizeof(abc));
xyz *x = (xyz*)malloc(sizeof(xyz));
def *de = (def*)malloc(sizeof(def));
x->pointer = (xyz*)temp;
ab = (abc*)x->pointer;
return 0;
}
Please help me.
I'm Affraid some serious lack of understanding pointers manifests in your code. Let me dissect it line by line to make clear where problems occur.
I numbered the statements in order to make easy references, assuming the type declarations as above.
int main()
{
int *temp, tmp;
abc* ab;
/* 1 */ tmp = 5;
/* 2 */ temp = &tmp;
/* 3 */ ab = (abc*)malloc(sizeof(abc));
/* 4 */ xyz *x = (xyz*)malloc(sizeof(xyz));
/* 5 */ def *de = (def*)malloc(sizeof(def));
/* 6 */ x = (xyz*)temp;
/* 7 */ ab = (abc*)x;
return 0;
}
First of all: You never clean up the memory allocated in 3, 4 and 5. Even for a simple test program, you should always take care of stuff like this.
Your first problem is line 6 where you blindly cast a pointer to an object of type int (4 bytes in memory) into a pointer to a structure of type xyz (4 or 8 bytes in memory, different type). What you do here is a complicated way to write x = (xyz*)&tmp;.
An action like that leads to following serious problems:
You just allocated memory in line 4. Now you overwrite this pointer with a pointer to your stack variable. Therefore you can't free the allocated memory anymore ==> Memory leak
Your newly assigned pointer to the stack variable becomes invalid after exiting the scope and can cause undefined behaviour.
Any write attempt to elements of x after line 6 can lead to corruption of the stack (and therefore undefined behaivour) due to a possible size mismatch of elements.
By line 7 you get the same problems again and even worse. The estimated sizeof(abc) is possibly 12 bytes. Accessing any element of abc after this line can lead to stack corruption again.
I still don't understand what you really are looking for but if you "have to" initialize a structure element through pointers there are a several ways:
If the struct ist known you can do it like this:
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
ab->c = 5;
// -- do other stuff
free(ab); ab = NULL;
}
If you need a pointer to the element 'c' you can do it like this:
int * c_ptr = NULL;
abc * ab = malloc(sizeof(abc));
if (ab != NULL) {
c_ptr = &(ab->c);
*c_ptr = 5;
//-- do other stuff
free(ab); ab = NULL;
}
Are you asking for this:
abc s;
s.c = 5;
That makes c 5. Or you could do thos:
abc s = {0,0,5};
That means, the first two members are initialized to 0, and third one (which is c) is initialized to 5.
Or if you've pointer, then you can do this:
abc *p = malloc(etc);
p->c = 5;
But then avoid using pointers and malloc. Use it when you really need them. In your code, I don't see any reason why you would need it. Use automatic variables, not pointers.
I think you would need to add this before return in your main() to get what you need.
ab->c = *(x->pointer);

Resources