Leetcode : AddressSanitizer heap-buffer-overflow - c

I am practicing the Leetcode question "Next Greater Node in Linked List"
and here is my code:
#define STACK_SIZE (10000U)
typedef struct ListNode Node;
static int stack[STACK_SIZE];
static int top=-1;
bool isEmpty()
{
return (top==-1);
}
void addToStack(int element)
{
stack[++top]=element;
}
void remFromStack()
{
--top;
}
int getStackTop()
{
return stack[top];
}
typedef struct ListNode Node;
int* nextLargerNodes(struct ListNode* head, int* returnSize) {
if (head == NULL) {
*returnSize = 0;
return NULL;
}
int len = 0;
Node *temp = head;
while (temp) {
len++;
temp = temp->next;
}
if (len > 0) {
int *result = malloc(len * sizeof(int));
*returnSize = len;
if (result == NULL) {
return NULL;
}
int j = 0;
while (j < len) {
result[j++] = 0;
}
temp = head;
addToStack(temp->val);
j = 0;
while (temp->next) {
temp = temp->next;
j++;
if (getStackTop() > temp->val) {
addToStack(temp->val);
} else {
int i = 0;
while (!isEmpty()) {
i++;
result[j - i] = temp->val;
remFromStack();
}
addToStack(temp->val);
}
}
return result;
} else {
return NULL;
}
}
And I am getting the following error:
=================================================================
==29==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6030000
WRITE of size 4 at 0x60300000000c thread T0
#2 0x7f55143382e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.s
0x60300000000c is located 4 bytes to the left of 20-byte region [0x60300
allocated by thread T0 here:
#0 0x7f55157c22b0 in malloc (/usr/local/lib64/libasan.so.5+0xe82b0)
#3 0x7f55143382e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.s
I am not sure what's wrong here.
Tried making sure all the code is correct, and when I test the code against my own test cases, it works perfectly fine, but when I submit the code, only then I am getting this error.
Note: The returned array must be malloced, assume caller calls free().
The utility functions dont have any malloc/ calloc called in them, so, that removes them from the equation.

Sizeof behaves differently on Leetcode.
Try to use strlen (if you are using char) OR other methods to find the size of a datatype you are trying to use.

Related

How to free a void pointer allocated after read a file

i have this structure filled by loading data from a file. I just found out by sanitaizer that string allocated in this way doesn't be free but i don't know how to do it cause it start as a void* item so i can't free it or give me error. I put here my code where, for every row read from the file there will be a leak of byte of an object.
=================================================================
==12111==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 86031 byte(s) in 711 object(s) allocated from:
#0 0x7ff09a17c867 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x55dd7970854b in load_dictionary (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x154b)
#2 0x55dd797086da in main (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x16da)
#3 0x7ff099ec9d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
I tried to free directly the variable row but then progema doesn't work cause a free the variable in the skipList and i can't read or search in it.
**Where i must put the free of the item? **
I put the code of the allocation and deallocation...with the read of file
There is a better and faster way to read the file?
Cause the process seems to stock, it takes more than 5/10 minutes to read the file but the algorithm does not proceed. It doesn't seem to freeze but it does nothing. With the sanitaizer it gives the error of memory that needs to be freed.
struct _SkipList {
Node *head;
unsigned int max_level;
int (*compare)(void*, void*);
};
struct _Node {
Node **next;
unsigned int size;
void *item;
};
static unsigned int load_dictionary(char *filename,SkipList *list )
{
unsigned int words_count = 0;
FILE *fp = fopen(filename, "r");
char *line = NULL;
size_t len = 0;
if (list == NULL)
{
list = create_skip_list();
}
char *word;
while (getline(&line, &len, fp) != -1)
{
words_count++;
word = malloc((len + 1) * sizeof(char));
strcpy(word, line);
strtok(word,"\n");
insert_skip_list(list, word);
}
free(line);
fclose(fp);
return words_count;
}
SkipList* create_skip_list(){
SkipList *list = malloc(sizeof(SkipList));
list->max_level = 0;
list->compare = NULL;
list->head = create_head_node(NULL,MAX_HEIGHT);
return list;
}
Node* create_head_node(void* item, int level){
if(level <1)
return NULL;
Node *node = malloc(sizeof(Node));
if(node == NULL){
printf("error malloc node\r\n");
/* Returning here prevent the program from accessing non allocated
* memory. */
return NULL;
}
node->item = item;
node->size = level;
node->next = (Node**)malloc(level * sizeof(Node *));
if (!node->next) {
printf("error malloc node next\r\n");
free(node);
return NULL;
}
for (int i = 0; i < level; i++)
{
node->next[i] = NULL;
}
return node;
}
void delete_node_array(Node* node){
if(node == NULL) return;
delete_node_array(node->next[0]);
node = free_node(node);
}
SkipList* delete_skip_list(SkipList *list){
if(list == NULL) return NULL;
delete_node_array(list->head);
free(list);
list=NULL;
return list;
}
Node* free_node(Node *node){
free(node->next);
free(node);
node = NULL;
return node;
}
int insert_skip_list(SkipList* list,void* item){
if (list == NULL || item ==NULL) return -1;
Node* node = create_node(item,random_level()); //is the same of create_head_node but without the initial check of the null Item
if(node == NULL){
printf("\nisert_skip_list:error malloc node");
return -1;
}
if(node->size > list->max_level){
list->max_level = node->size;
}
Node *x = list->head;
for (int k = list->max_level-1; k >= 0; k--)
{
if(x->next[k] == NULL || strcmp(item,x->next[k]->item) < 0 ){
if(k < node->size){
node->next[k] = x->next[k];
x->next[k] = node;
}
}else{
x = x->next[k];
k++;
}
}
return 0;
}
I solved by put in :
Node* free_node(Node *node){
free(node->item); --> new line
free(node->next);
free(node);
node = NULL;
return node;
}
But this is strange cause the first time didn't work. Otherwise still too slow for a correct solution. Any suggest how to improve the read function's speed?

Balanced Brackets Checker always gives incorrect output

I have created a function which uses Linked List to check whether an expression is balanced or not. A balanced expression has no. of opening brackets equal to no. of closing brackets.
But the function Bracket Balancing always gives "unbalanced" as the output.
CODE:
#include <stdio.h>
#include <stdlib.h>
struct LL {
char data;
struct LL *next;
};
int isEmpty(struct LL *top) {
if (top == NULL) {
return 1;
}
else {
return 0;
}
}
int isFull(struct LL *top) {
struct LL *n = malloc(sizeof(struct LL *));
if (n == NULL) {
return 1;
}
else {
return 0;
}
}
struct LL *push(struct LL *top, char x) {
if (isFull(top)) {
printf("Stack Overflow\n");
}
else {
struct LL *n = malloc(sizeof(struct LL));
n->data = x;
n->next = top;
top = n;
}
return top;
}
struct LL *pop(struct LL *top) {
if (isEmpty(top)) {
printf("Stack Underflow\n");
}
else {
struct LL *n = malloc(sizeof(struct LL));
n = top;
top = top->next;
free(n);
}
return top;
}
int BracketBalancing (char *exp) {
struct LL *top = malloc(sizeof(struct LL));
top->next = NULL;
for (int i = 0; exp[i] != '\0'; i++) {
if (exp[i] == '(') {
push(top, exp[i]);
}
else if (exp[i] == ')') {
if (isEmpty(top)) {
return 0;
}
pop(top);
}
}
if (isEmpty(top)) {
return 1;
}
else {
return 0;
}
}
MAIN:
int main(int argc, char const *argv[]) {
int n;
char *expression = (char *)malloc(sizeof(char));
printf("Enter the length of the expression for Bracket Balancing\n");
scanf("%d", &n);
printf("Enter the expression for Bracket Balancing\n");
for (int i = 0; i < n; i++) {
scanf("%c ", &expression[i]);
}
getchar();
if (BracketBalancing(expression)) {
printf("The expression is balanced\n");
}
else if (!BracketBalancing(expression)) {
printf("This expression is unbalanced\n");
}
return 0;
}
Example:
Input:
Enter the length of the expression for Bracket Balancing
4
Enter the expression for Bracket Balancing
1+()
Output:
This expression is unbalanced
In the above example, Despite the expression being balanced the output generated is "This expression is unbalanced".
Please correct my code.
This is how you initialize your list:
struct LL *top = malloc(sizeof(struct LL));
top->next = NULL;
And this is isEmpty():
int isEmpty(struct LL *top)
{
if (top == NULL)
{
return 1;
}
else
{
return 0;
}
}
But: top starts with a value != NULL, so isEmtpy() will not return 1, although our list should be empty in the beginning.
Your implementation of push() should work fine when you pass NULL, so you can just initialize struct LL *top = NULL; instead of creating the first element rightaway.
there other bugs in your code, e.g.:
in pop() you do
struct LL *n = malloc(sizeof(struct LL));
n = top;
thus, the result of malloc() is directly overwritten() in the next line
in isFull() you produce a memory leak as you call malloc() and never use or free() the buffer returned. That function doesn't make sense anyway, just check the result of malloc()s where your really want to use the buffer returned.
** Edit **
What I haven't seen before, you also never use the return value of push() and pop() so the new top determined by these function is lost. Replace push(top, ...); by top = push(top,...); and pop(top); by top = pop(top);

C Language - Tried to make an array stack data structure to implement a undo/redo "prototype", why isn't it working? :(

Basically I made a create_app() function to allocate 2 nodes in the stack, each having a pointer to an array[max]; undo() pops the last element, and before returning it, it adds it into the REDO node's array. redo() does the opposite, pops the last element in it's array, putting it into Undo's array before returning it. What did I do wrong ?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node *node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack != NULL){printf("Out of space!");}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return(S->tos==-1);
}
int
isFull(STACK S)
{
return(S->tos>=S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
int
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
int
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Some small errors were in your code, like these ones in create_app() which seem like typos.
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
^
|
if(UNDO->arr_stack != NULL){printf("Out of space!");}
^
|
...
and some int returning functions did not return anything in the else part which gave some warnings.
Here is the modified code, which worked fine for me
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node* node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack = (int *) malloc(max * sizeof(int));
REDO->arr_stack = (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack == NULL){printf("Out of space!");
return NULL;}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return (S->tos == -1);
}
int
isFull(STACK S)
{
return (S->tos >= S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
void
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
void
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Result:
3223
However, always take precaution in deallocating the memory malloced using free().

I have problems implementing a stack

I have a question about my piece of code here: I tried to write a function, its name is take, the function can get only one int parameter and have to return back the middle number that was inserted. The function has to use in, as minimum memory as possible. I tried to use in a stack. Its my implementation. The problem is that the program doesn't return a value after the third insertion.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int take (int);
typedef struct stack
{
int num;
struct stack *next;
}stack;
stack first;
bool isit = true;
int counter = -1;
int main()
{
printf("%d",take(5));
printf("%d", take(6));
printf("%d", take(7));
return 0;
}
int take(int value)
{
if (isit)
{
isit = false;
first.num = value;
first.next = NULL;
}
else
{
static stack newone;
newone.num = value;
newone.next = NULL;
stack temp = first;
while (temp.next != NULL)
{
temp = *temp.next;
}
temp.next = &newone;
}
stack *temp1 = malloc(sizeof(stack));
*temp1 = first;
counter++;
if (counter > 1 && counter % 2 == 0)
{
temp1 = temp1->next;
}
return (temp1->num);
}
A big problem in your code is that you use global variables where you don't need
them. This creates problems that don't expect, like this:
int take(int value)
{
...
static stack newone;
newone.num = value;
newone.next = NULL;
stack temp = first;
while (temp.next != NULL)
{
temp = *temp.next;
}
temp.next = &newone;
The static stack newone is a static variable, it means it will be always the
same every time you call take, you are overwriting the values all the time,
specially the next pointer.
For this reason, avoid using global variables when you can perfectly declare
them in the main function and pass them to the other functions.
Also you malloc part doesn't make any sense. You want minimal memory footprint
but you allocate memory which is lost after temp1 = temp1->next;.
If you want a minimal memory footprint and not having to allocate memory with
malloc, then you can declare an array of fixed length and use it as a stack,
something like this:
typedef struct stack
{
int stack[20];
size_t len;
size_t size;
} Stack;
void stack_init(Stack *stack)
{
if(stack == NULL)
return;
stack->size = sizeof stack->stack / sizeof stack->stack[0];
stack->len = 0;
}
int stack_is_empty(Stack *stack)
{
if(stack == NULL)
return 1;
return stack->len == 0;
}
int stack_is_full(Stack *stack)
{
if(stack == NULL)
return 0;
return stack->len == stack->size;
}
int stack_push(Stack *stack, int value)
{
if(stack == NULL)
return 0;
if(stack_is_full(stack))
return 0;
stack->stack[stack->len++] = value;
return 1;
}
int stack_pop(Stack *stack, int *val)
{
if(stack == NULL)
return 0;
if(stack_is_empty(stack))
return 0;
stack->len--;
if(val)
*val = stack->stack[stack->len];
return 1;
}
int take(Stack *stack, int value)
{
if(stack == NULL)
return 0;
if(stack_push(stack, value) == 0)
fprintf(stderr, "stack is full, cannot push\n");
return stack->stack[stack->len / 2];
}
int main(void)
{
Stack stack;
stack_init(&stack);
printf("%d", take(5));
printf("%d", take(6));
printf("%d", take(7));
return 0;
}

error expected expression before "STACK"

typedef struct student *std_ptr;
struct student
{
int number;
std_ptr next;
};
typedef std_ptr STACK;
create_stack(void)
{
STACK S;
S = (STACK) malloc( sizeof( struct student ) );
if(S == NULL) printf("out of space!");
return S;
}
void push(int x, STACK S)
{
std_ptr tmp;
tmp = (std_ptr) malloc(sizeof(struct student));
if(tmp == NULL) printf("out of space!");
else
{
tmp -> number = x;
tmp -> next = S -> next;
S -> next = tmp;
}
}
int main()
{
push(12058010,STACK S);
return 0;
}
Im trying to call function and I get error: expected expression before stack.I also tried to call the function like that
int main()
{
push(12058010,S);
return 0;
}
This time I get error: 'S' undeclared(first use in this function)
Thank you for your help!
Define the variable s by doing:
STACK s;
Initialise it:
s = create_stack();
Test whether the initialisation succeeded:
if (NULL == s)
{
return EXIT_FAILURE;
}
Use it by calling push() like this:
push(12058010, s);
All together this could look like this:
int main(void)
{
STACK s = create_stack(); /* This merges step 1 and 2. */
if (NULL == s)
{
return EXIT_FAILURE;
}
push(12058010, s);
return EXIT_SUCCES;
}
S is neither in the global scope nor in the scope of main().
I suspect you meant to write STACK S = create_stack(); as the first statement in main().
Don't forget to free the allocated memory as well.

Resources