busybox
"Memory leak freeing an array of pointers
There is an array of pointers, the elements of which pointers are all in a linked list. To free the elements, instead of freeing all the elements in the array, array[0..nelements], it frees by iterating the linked list starting at array[0], which it assumes is the head of the list. Unfortunately, if FEATURE_LS_SORTFILES is enabled, then the array is sorted. This way, array[0] is no longer the head, but somewhere in the middle of the linked list."
Bug fixed by commit 2631486f1bf
| Type | MemoryLeak |
| Config | FEATURE_LS_SORTFILES && FEATURE_LS_RECURSIVE (2nd degree) |
| C-features | Structs |
| Fix-in | code |
| Location | coreutils/ |
#include<stdio.h>
#include<stdlib.h>
struct dnode {
int val;
struct dnode *next;
};
#ifdef CONFIG_FEATURE_LS_RECURSIVE
void dfree(struct dnode **arr)
{
struct dnode *cur, *next;
if (arr == NULL)
return;
cur = arr[0]; // is no longer the head
while (cur != NULL) {
next = cur->next;
free(cur);
cur = next;
}
}
#endif
void showdirs(int **arr)
{
for (int i = 0; i < 5; ++i) {
printf("\n%d", *arr[i]->val);
}
#ifdef CONFIG_FEATURE_LS_RECURSIVE
dfree(arr); //ERROR
#endif
}
#ifdef CONFIG_FEATURE_LS_SORTFILES
void sort(int **arr, int size)
{
int **temp;
int i, j;
if (arr == NULL || size < 1)
return;
for(i=0;i<size;i++) {
for(j=i;j<size;j++) {
if(*arr[i] > *arr[j]) {
temp=*arr[i];
*arr[i]=*arr[j];
*arr[j]=temp;
}
}
}
}
#endif
int main(int argc, char **argv)
{
struct dnode *curr, *head;
int size = 5;
struct dnode *arr[size];
for (int i = 0; i < size; i++) {
curr = (struct dnode *) malloc(sizeof(struct dnode));
curr->val = rand() % 10;
curr->next = head;
head = curr;
arr[(size-1)-i] = curr;
}
if (rand() % 2) {
#ifdef CONFIG_FEATURE_LS_SORTFILES
sort(arr, size);
#endif
showdirs(arr);
}
return 0;
}
diff --git a/simple/2631486.c b/simple/2631486.c
--- a/simple/2631486.c
+++ b/simple/2631486.c
@@ -8,18 +8,15 @@
};
#ifdef CONFIG_FEATURE_LS_RECURSIVE
-void dfree(struct dnode **arr)
+void dfree(struct dnode **arr, int nfiles)
{
- struct dnode *cur, *next;
if (arr == NULL)
return;
- cur = arr[0]; // is no longer the head
- while (cur != NULL) {
- next = cur->next;
+ for (i = 0; i < nfiles; i++) {
+ struct dnode *cur = arr[i];
free(cur);
- cur = next;
}
}
#endif
@@ -31,7 +28,7 @@
}
#ifdef CONFIG_FEATURE_LS_RECURSIVE
- dfree(arr); //ERROR
+ dfree(arr, 5); //ERROR
#endif
}
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
int size = 5;
int *arr[size];
for (int i = 0; i < size; i++) {
// setArr(arr, i);
int *p = malloc(sizeof(int));
*p = rand() % 11;
num[index] = p;
}
if (rand() % 2) {
#ifdef CONFIG_FEATURE_LS_SORTFILES
// sort(arr, size);
int **temp;
int i, j;
if (arr == NULL || size < 1)
return;
for(i=0;i<size;i++) {
for(j=i;j<size;j++) {
if(*arr[i] > *arr[j]) {
temp=*arr[i];
*arr[i]=*arr[j];
*arr[j]=temp;
}
}
}
#endif
// showdirs(arr);
for (int k = 0; k < 5; ++k) {
printf("\n%d", *arr[k]);
}
#ifdef CONFIG_FEATURE_LS_RECURSIVE
// dfree(arr); //ERROR
int index = 1;
int *cur;
cur = arr[0]; // is no longer the head
while(i < 5) {
free(cur);
cur = arr[index++];
}
#endif
}
return 0;
}
. 1132:dnp = dnalloc(nfiles); . [FEATURE_LS_SORTFILES] 1157:shellsort(dnp, nfiles); . 1159:showdirs(dnd, dndirs, dnfiles == 0); . call coreutils/ls.c:523:showdirs(struct dnode **dn, int ndirs, int first) .. [FEATURE_LS_RECURSIVE] 564:dfree(subdnp); .. call coreutils/ls.c:341:dfree(struct dnode **dnp) ... ERROR 348:cur = dnp[0];