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];