From 2631486f1bfac59f9217350effcda627da7be875 Mon Sep 17 00:00:00 2001
From: Rob Landley <rob@landley.net>
Date: Tue, 2 May 2006 19:46:52 +0000
Subject: Patch from Shaun Jackman:

ls has an ugly bug. ls uses an array of pointers, the elements of
which 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, ls also sorts the array! So,
array[0] is no longer the head, but somewhere in the middle of the
linked list. This patch fixes this bug, and also adds an
ENABLE_FEATURE_CLEAN_UP stanza.
---
 coreutils/ls.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/coreutils/ls.c b/coreutils/ls.c
index c9d24ff4a..9cbb4cab7 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -338,20 +338,18 @@ static struct dnode **dnalloc(int num)
 }
 
 #ifdef CONFIG_FEATURE_LS_RECURSIVE
-static void dfree(struct dnode **dnp)
+static void dfree(struct dnode **dnp, int nfiles)
 {
-	struct dnode *cur, *next;
+	int i;
 
 	if (dnp == NULL)
 		return;
 
-	cur = dnp[0];
-	while (cur != NULL) {
+	for (i = 0; i < nfiles; i++) {
+		struct dnode *cur = dnp[i];
 		if(cur->allocated)
 			free(cur->fullname);	/* free the filename */
-		next = cur->next;
 		free(cur);		/* free the dnode */
-		cur = next;
 	}
 	free(dnp);			/* free the array holding the dnode pointers */
 }
@@ -561,7 +559,7 @@ static void showdirs(struct dnode **dn, int ndirs, int first)
 					free(dnd);	/* free the array of dnode pointers to the dirs */
 				}
 			}
-			dfree(subdnp);	/* free the dnodes and the fullname mem */
+			dfree(subdnp, nfiles);	/* free the dnodes and the fullname mem */
 #endif
 		}
 	}
@@ -1151,13 +1149,19 @@ int ls_main(int argc, char **argv)
 			shellsort(dnf, dnfiles);
 #endif
 			showfiles(dnf, dnfiles);
+			if (ENABLE_FEATURE_CLEAN_UP)
+				free(dnf);
 		}
 		if (dndirs > 0) {
 #ifdef CONFIG_FEATURE_LS_SORTFILES
 			shellsort(dnd, dndirs);
 #endif
 			showdirs(dnd, dndirs, dnfiles == 0);
+			if (ENABLE_FEATURE_CLEAN_UP)
+				free(dnd);
 		}
 	}
+	if (ENABLE_FEATURE_CLEAN_UP)
+		dfree(dnp, nfiles);
 	return (status);
 }
-- 
cgit v1.2.3