[pacman-dev] [PATCH] Fix group selection entry for large inputs

Dan McGee dan at archlinux.org
Mon Jul 25 11:08:41 EDT 2011


Hardcoding anything always ends up burning you, and the arbitrary length
of 64 here did just that. Add the ability to reallocate the readline
buffer for longer inputs if necessary, and add other error checking as
approprate. This also plugs one small memory leak of the group
processing code selection array.

Addresses FS#24253.

Signed-off-by: Dan McGee <dan at archlinux.org>
---
 src/pacman/sync.c |   11 ++++++++++-
 src/pacman/util.c |   38 +++++++++++++++++++++++++++++++++++---
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index c56934b..6962306 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -644,7 +644,15 @@ static int process_group(alpm_list_t *dbs, char *group)
 				group);
 		select_display(pkgs);
 		char *array = malloc(count);
-		multiselect_question(array, count);
+		if(!array) {
+			ret = 1;
+			goto cleanup;
+		}
+		if(multiselect_question(array, count)) {
+			ret = 1;
+			free(array);
+			goto cleanup;
+		}
 		int n = 0;
 		for(i = pkgs; i; i = alpm_list_next(i)) {
 			if(array[n++] == 0)
@@ -657,6 +665,7 @@ static int process_group(alpm_list_t *dbs, char *group)
 				goto cleanup;
 			}
 		}
+		free(array);
 	} else {
 		for(i = pkgs; i; i = alpm_list_next(i)) {
 			pmpkg_t *pkg = alpm_list_getdata(i);
diff --git a/src/pacman/util.c b/src/pacman/util.c
index f695ffb..53dbd63 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -796,8 +796,9 @@ static int multiselect_parse(char *array, int count, char *response)
 
 int multiselect_question(char *array, int count)
 {
-	char response[64];
+	char *response, *lastchar;
 	FILE *stream;
+	size_t response_len = 64;
 
 	if(config->noconfirm) {
 		stream = stdout;
@@ -806,19 +807,45 @@ int multiselect_question(char *array, int count)
 		stream = stderr;
 	}
 
+	response = malloc(response_len);
+	if(!response) {
+		return -1;
+	}
+	lastchar = response + response_len - 1;
+	/* sentinel byte to later see if we filled up the entire string */
+	*lastchar = 1;
+
 	while(1) {
 		memset(array, 1, count);
 
 		fprintf(stream, "\n");
 		fprintf(stream, _("Enter a selection (default=all)"));
 		fprintf(stream,	": ");
+		fflush(stream);
 
 		if(config->noconfirm) {
 			fprintf(stream, "\n");
 			break;
 		}
 
-		if(fgets(response, sizeof(response), stdin)) {
+		if(fgets(response, response_len, stdin)) {
+			const size_t response_incr = 64;
+			/* handle buffer not being large enough to read full line case */
+			while(*lastchar == '\0' && lastchar[-1] != '\n') {
+				response_len += response_incr;
+				response = realloc(response, response_len);
+				if(!response) {
+					return -1;
+				}
+				lastchar = response + response_len - 1;
+				/* sentinel byte */
+				*lastchar = 1;
+				if(fgets(response + response_len - response_incr - 1,
+							response_incr + 1, stdin) == 0) {
+					free(response);
+					return -1;
+				}
+			}
 			strtrim(response);
 			if(strlen(response) > 0) {
 				if(multiselect_parse(array, count, response) == -1) {
@@ -826,9 +853,14 @@ int multiselect_question(char *array, int count)
 					continue;
 				}
 			}
+			break;
+		} else {
+			free(response);
+			return -1;
 		}
-		break;
 	}
+
+	free(response);
 	return(0);
 }
 
-- 
1.7.6



More information about the pacman-dev mailing list