LeetCode ERROR: AddressSanitizer: heap-buffer-overflow - c

My code can print the answer correctly, but when I try to return the ans variable, it shows heap-buffer-overflow.
char * longestPalindrome(char * s){
int le = strlen(s);
int t = 0, it = 0;
int start = 0, end = 0;
int max = 0;
for (int i = 0; i < le; i++){
it = i;
for (int j = le-1; j > i; j--){
t = 0;
while (s[it] == s[j]){
t++;
j--;
it++;
if (j < i){
break;
}
}
if (max < t){
max = t;
start = i;
end = it-1;
}
it = i;
}
}
char *ans;
ans = (char *)malloc(sizeof(char)*(max));
for(int i = 0; i < max; i++){
ans[i] = s[start+i];
}
return ans;
}
The error description is like:
==34==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000033 at pc 0x557f4a2709ab bp 0x7fff8135edd0 sp 0x7fff8135edc0
READ of size 1 at 0x602000000033 thread T0
#2 0x7f4879d2e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x602000000033 is located 0 bytes to the right of 3-byte region [0x602000000030,0x602000000033)
allocated by thread T0 here:
#0 0x7f487a973bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#3 0x7f4879d2e0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

You need to allocate one more byte for ans to make room for the \0 that should be at the end of the string:
// ...
char *ans = malloc(max + 1); // one extra byte
for(int i = 0; i < max; i++){
ans[i] = s[start+i];
}
ans[max] = '\0'; // and remember to terminate the string
return ans;
}
Copying can also be done simpler by using memcpy and don't forget to check that malloc succeeds:
char *ans = malloc(max + 1);
if (ans) { // check that malloc succeeded
memcpy(ans, s + start, max); // instead of the loop
ans[max] = '\0';
}
return ans;
}

Related

Variable reset to 0 and come with Segementation fault (core dumped) in C

Within a function, I had seven print statements that prints out the value of totalIteration variable. It used to and supposed to remain 77, however, right after my function call to ratio(), the variable turned to 0. I did not modify it anywhere between the two print statements, so I am very confused on why this happened.
Code:
float get_running_ratio() {
int maxCount = 0;
int maxIteration = 0;
int totalIteration = 0;
float avgVal = 0.0;
totalIteration = get_iteration_no(rand());
int size = get_arr_size(rand());
for (int i = 0; i < totalIteration; i++) {
printf("%d\n", totalIteration); // print statement
char *arr = malloc(size * sizeof(char));
printf("%d\n", totalIteration); // print statement
for (int j = 0; j < size; j++) {
arr[j] = get_arr_val(rand());
}
printf("%d\n", totalIteration); // print statement
int tem = maxCount;
printf("%d\n", totalIteration); // print statement
float temp = ratio(arr, size, &tem);
printf("%d\n", totalIteration); // print statement
if (temp > maxCount) {
maxCount = temp;
maxIteration = i;
}
printf("%d\n", totalIteration); // print statement
free(arr);
printf("%d\n", totalIteration); // print statement
avgVal = avgVal + temp;
}
avgVal = avgVal / totalIteration;
printf("total number of iterations: %d\n", totalIteration);
printf("the iteration number with the maximum number of vowels: %d",
maxIteration);
return avgVal;
}
float ratio(char *arr, int size, int *maxCountPointer) {
int vowel = 0;
for (int i = 0; i < size; i++) {
if (arr[i] == 'A' || arr[i] == 'E' || arr[i] == 'I' || arr[i] == 'O' ||
arr[i] == 'U') {
vowel = vowel + 1;
}
maxCountPointer[i] = vowel / (size - vowel);
vowel = 0;
}
if (*maxCountPointer < vowel) {
*maxCountPointer = vowel;
}
free(arr);
return (float)vowel / (size - vowel);
}
Output:
77
77
77
77
0
0
0
total number of iterations: 0
Segmentation fault (core dumped)
As #Cheatah mentions, you have a double free() in ratio().
More pressingly, you have int *maxCountPointer, which you use
as if it was an array (maxCountPointer[i] = ...)
as if it was a regular int pointer (*maxCountPointer = ...)
and since you only pass it a pointer to a single int on stack (&tem), that array write ends up overwriting other memory (stack variables in the calling function, for instance).

How to dynamically increase size of any structure objects during runtime?

I am a bit of a beginner in C language. I was trying out a task of dynamically reallocating memory as the input comes through(although for this test I am doing a normal task, later will try to scale it up). the issue I am facing is I am unable to access the memory while writing into it. Can anyone please help me understand where I am going wrong in this code. thanks in advance.
code:
#include<stdio.h>
#include<stdlib.h>
struct ai {
int* a;
char* b;
};
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
} ```
You have missing initialization of your pointers and some other issues...
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
In C you should not cast the result of malloc. In best case it is useless. In worst case it hides real problems.
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
Here comes the reason for your segmentation fault:
You do not have any memory reserved for a and b except for the first element test[0]. All other array elements test[i] do not contain any useful data. Dereferencing these pointers is undefined behaviour.
You must allocate memory for each field after you enlarged your array.
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
You should never assign the return value of realloc to the same variable that you passed into the function. In case of an error you will get NULL return value and then your initiali pointer is lost.
Also here: don't cast for realloc as well.
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
Same here: Don't assign to same variable and don't cast the result of realloc.
Finally: Here goes the missing part:
test[i+1].a = malloc(sizeof(*test[0].a));
test[i+1].b = malloc(sizeof(*test[0].b));
}
Of course you should check all return values for error results.
Not related to the segmentation fault, but still worth to fix:
You increment the size of each array after you used the last element.
This prepares the new element for being filled in next iteration of the loops. But in case of the last iteration it allocated an unused element for both the intern pointers a and b as well as the outer array test.
You will have some unused elements:
test[0].a[4]
test[0].b[4]
test[1].a[4]
test[1].b[4]
test[2].a[0]
test[2].b[0]
An improved solution could look like this (not tested)
I start with each pointer being NULL and use realloc right before the new element is used to avoid the extra elements.
int main(void)
{
struct ai *test = NULL
void *tmp;
// storing info
for (int i = 0; i < 2; i++)
{
tmp = realloc(test, (i+1) * sizeof(*test))
if (tmp == NULL)
exit(1);
test = tmp;
test[i].a = NULL;
test[i].b = NULL;
for (int j = 0; j < 4; j++)
{
tmp = realloc(test[i].a, (j+1) * sizeof(test[i].a[0]));
if (tmp == NULL)
exit(1);
test[i].a = tmp;
tmp = realloc(test[i].b, (j+1) * sizeof(test[i].b[0]));
if (tmp == NULL)
exit(1);
test[i].b = tmp;
test[i].a[j] = j;
test[i].b[j] = 65 + j;
}
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
}

C: Problems Using Free() on Structs Elements, Strange Behivor

I'm having problems by freeing the elements on my struct.
long code warning
typedef struct bingo
{
char board[5][5];
int* luckNum;
int* boardNum;
} bingo;
void update(bingo *pBingo,int num); //Function that gets a struct, number and checks if he is in the board, if it does he change it to "X"
int main(void)
{
srand(time(NULL));
int i, j, m, k, temp[75], *parr;
bingo player;
//For rellocating them later
if (!(player.luckNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
if (!(player.boardNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
//giving temp values of 1-75
for ( i = 0; i < 75; i++)
{
temp[i] = i + 1;
}
//Giving the player board random values of 1-75 without repeating the same number twice
for ( i = 0; i < 5; i++) //Passing on the rows
{
for (j = 0; j < 5; j++) //Passing on the columns
{
//
do
{
k = rand() % 75; //from 0-74
}
while (temp[k] == NULL); //while temp[k] is marked
player.board[i][j] = temp[k];
temp[k] = NULL; //NULL as a "flag" that marks the cell as taken (for not taking the same number twice)
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));
player.luckNum[i*j + j] = player.board[i][j];
}
}
//sets luckNum
for ( i = 0; i < 25; i++)
{
printf("%d ", player.luckNum[i]);
update(&player, player.luckNum[i]);
}
printf("\n");
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
free(player.boardNum);
free(player.luckNum);
getchar();
return 0;
}
void update(bingo *pBingo, int num)
{
int i, j, k;
static int counter = 0,luckCounter = 25;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (num == (int) (pBingo->board[i][j]))
{
pBingo->board[i][j] = 'X';
counter++;
pBingo->boardNum = (int*) realloc(pBingo->boardNum, sizeof(int)*counter);
pBingo->boardNum[counter] = num;
for (k = 0; k < luckCounter; k++)
{
if (pBingo->luckNum[k] == num)
{
num = pBingo->luckNum[k];
pBingo->luckNum[k] = pBingo->luckNum[luckCounter-1];
pBingo->luckNum[luckCounter-1] = num;
pBingo->luckNum = (int*) realloc(pBingo->luckNum, sizeof(int)*luckCounter);
luckCounter--;
}
}
}
}
}
}
Can anyone recognize what interrupts the free() function from freeing the memory?. I'm new to C and working on this code about good days so sorry for my ignorance about free() function, can anyone help me?
Ilan,
Don't be afraid to post your code with the necessary includes. First of all, are you heeding to the warnings of your compiler?
A few problem areas:
while (temp[k] == NULL)
You can research the difference between 0, NULL and '\0' but reserve the use of NULL for pointers. Also:
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
Printf is expecting an integer and you're giving it a pointer. Finally, to address what I think is your problem, when you write "..interrupts the free() function from freeing the memory?" Do you mean your program simply not returning? If so then get rid of the final getchar(). You're still going to have at least one leak in this program. This address of this malloc:
if (!(player.luckNum = (int*) malloc(sizeof(int))))
will be lost as you assigned luck.Num a new address here without freeing the first:
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));

Sort a 2D array of strings in C

I'm currently reading in a list of words from a file and trying to sort them line by line.
I can read each line in and print the words out just fine, but I can't seem to sort each line individually. The first line is sorted, but the second is not. Can anyone see where I'm going wrong? Thanks!
int fd;
int n_char = 0;
int charCount = 0, wordCount = 0, lineCount = 0;
int wordsPerLine[100];
char buffer;
char words[6][9];
fd = open(inputfile, O_RDONLY);
if (fd == -1) {
exit(1);
}
wordsPerLine[0] = 0;
/* use the read system call to obtain 10 characters from fd */
while( (n_char = read(fd, &buffer, sizeof(char))) != 0) {
if (buffer == '\n' || buffer == ' ') {
words[wordCount][charCount] = '\0';
charCount = 0;
wordCount++;
wordsPerLine[lineCount] += 1;
if (buffer == '\n') {
lineCount++;
wordsPerLine[lineCount] = 0;
}
} else {
words[wordCount][charCount++] = buffer;
}
}
printf("Num Words: %d --- Num Lines: %d\n", wordCount, lineCount);
char tmp[9];
int m, n;
int i, x, totalCount = 0;
for (i = 0; i < lineCount; i++) {
for (x = 0; x < wordsPerLine[i]; x++) {
/* iterate through each word 'm' in line 'i' */
for(m = 0; m < wordsPerLine[i]; m++) {
for(n = 0; n < wordsPerLine[i]; n++) {
if(strcmp(words[n-1], words[n])>0) {
strcpy(tmp, words[n-1]);
strcpy(words[n-1], words[n]);
strcpy(words[n], tmp);
}
}
} /* end sorting */
}
}
printf("Sorted:\n");
totalCount = 0;
for(i = 0; i < lineCount; i++) {
printf("Line %d (%d words)\n", i + 1, wordsPerLine[i]);
for(x = 0; x < wordsPerLine[i]; x++) {
printf("%s\n", words[totalCount++]);
}
}
My sample input file is:
great day out
foo bar food
Let's go by small parts...
To see if the problem is in the reading, comment the reading part and try to add:
char words[][9] = {"great", "day", "out", "foo", "bar", "food"};
and set the counters to the value they would with this input also...
Your loop is accessing some data out of the bounds... I would recommend you to try your sorting code with an array of numbers first and see if it is sorting them correctly...
#include<stdio.h>
#define N 6
int main()
{
char words[][9] = {"great", "day", "out", "foo", "bar", "food"};
int numbers[] = {20, 10, 50, 5, 30, -50};
int i, j, temp;
for(i = 0; i < N - 1; i++)
for(j = 0; j < N - 1; j++)
if(numbers[j] > numbers[j + 1])
{
temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
for(i = 0; i < N; i++)
{
printf("%d\n", numbers[i]);
//printf("%s\n", words[i]);
}
}
Note also that this is the least efficient implementation of bubble sort (but is the same you provided), you can improve it by adding a variable to check in the inner loop some change happened for instance(which would mean that it is already sorted and you can stop sorting)...
Also, after each iteration on the outter loop one element is going to be placed in its final place (try to find out which one), which means that you won't need to consider this element in the next iteration, so after each iteration in the outer loop the number of elements compared in the inner loop can be reduced by 1...
you can find more info about bubble sort here
/* iterate through each line */
for (i = 0; i < lineCount; i++) {
/* iterate through each word 'm' in line 'i' */
for(m = 0; m < wordsPerLine[i]; m++) {
for(n = m+1; n < wordsPerLine[i]; n++) {
if(strcmp(words[n + totalCount], words[m + totalCount]) < 0) {
strcpy(tmp, words[m + totalCount]);
strcpy(words[m + totalCount], words[n + totalCount]);
strcpy(words[n + totalCount], tmp);
}
}
} /* end sorting */
totalCount += wordsPerLine[i];
}
I just needed to keep a running count of each word per line, so i know what line to start comparing with

Stack around the variable 's' was corrupted

I got this error in my rc4 algorithm, it works well, but i got this error every time when the message is too big, like 1000kB, here is the code:
char* rc4(const int* key, int key_size, char* buff, int buff_size){
int i, j, k;
int s[255], rk[255]; //rk = random_key
char* encrypted = alloc_char_buffer(buff_size);
for (i = 0; i < 255; i++){
s[i] = i;
rk[i] = key[i%key_size];
}
j = 0;
for (i = 0; i < 255; i++){
j = (j + s[j] + rk[i]) % 256;
SWITCH(s + i, s + j);
}
i = 0;
j = 0;
for (k = 0; k < buff_size; k++){
i = (i + 1) % 256;
j = (j + s[i]) % 256;
SWITCH(s + i, s + j);
//try{
//}
//catch ()
encrypted[k] = (char)(s[(s[i] + s[j]) % 256] ^ (int)buff[k]);
}
encrypted[buff_size] = 0;
return encrypted;
}
at the end o the last loop i got this error, i think this is some type of buffer overflow error, the only variable able to do that is the 'encrypted' but at the end of the loop, the value of the variable 'k' have the exactly same value of 'buff_size' that is used to alloc memory for 'encrypted', if someone can help i'll thank you
the 'encrypted' is "non-null terminated", so if the string have 10 bytes i will allocate only 10 bytes, not 11 for the '\0'
if you need, here is the code for alloc_char_buffer(unsigned int)
char* alloc_char_buffer(unsigned int size){
char* buff = NULL;
buff = (char*)calloc(size+1, sizeof(char));
if (!buff)
_error("program fail to alloc memory.");
return buff;
}
SWITCH:
//inversão de valores
void SWITCH(int *a, int *b){
*(a) = *(a) ^ *(b); //a random number
*(b) = *(a) ^ *(b); //get a
*(a) = *(a) ^ *(b); //get b
}
char* encrypted = alloc_char_buffer(buff_size);
/* ... */
encrypted[buff_size] = 10;
Here is the problem. You allocate buff_size elements. Thus, the last valid index is buff_size-1, not buff_size.
Another issue:
j = (j + s[j] + rk[i]) % 256;
Thus the range of j is [0, 255], but the legal index of s is only [0, 254]. You should either declare s as a 256-element array or review the algorithm implementation.
Your following line is creating the problem as you are trying to access beyond your allocated memory.
encrypted[buff_size] = 10;
Additionally, you should avoid use calloc instead of writing your own function alloc_char_buffer. It would allocate memory and initialize with 0.
calloc(buff_size, sizeof(char));

Resources