summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-07-25 17:05:36 +0200
committerDan McGee <dan@archlinux.org>2011-07-25 17:07:48 +0200
commit88644e181db49f3f94e6891166823fd5f46acbcc (patch)
tree06fc9a0a97cc51db4bd90a831b94a85af15a938d
parent005eab0a080925d0d6f780d751f9019dafbafc64 (diff)
downloadpacman-88644e181db49f3f94e6891166823fd5f46acbcc.tar.gz
pacman-88644e181db49f3f94e6891166823fd5f46acbcc.tar.xz
Fix group selection entry for large inputs
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@archlinux.org>
-rw-r--r--src/pacman/sync.c11
-rw-r--r--src/pacman/util.c38
2 files changed, 45 insertions, 4 deletions
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index c56934b6..6962306a 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 f695ffba..53dbd637 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);
}