From 50296303d8066a327c17cbd10c55a02e0b69b6ba Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mon, 20 Oct 2014 12:04:34 -0400 Subject: [PATCH 23/31] Make -o's behavior actually match the documented behavior. Also make it a bit better and reporting errors. This should actually resolve https://github.com/vathpela/efibootmgr/issues/12 . Signed-off-by: Peter Jones --- src/efibootmgr/efibootmgr.c | 94 +++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/src/efibootmgr/efibootmgr.c b/src/efibootmgr/efibootmgr.c index b5d4147..ec083af 100644 --- a/src/efibootmgr/efibootmgr.c +++ b/src/efibootmgr/efibootmgr.c @@ -34,10 +34,11 @@ #include #include +#include +#include #include #include #include -#include #include #include #include @@ -596,52 +597,89 @@ is_current_boot_entry(int b) return 0; } +static void +print_error_arrow(char *message, char *buffer, off_t offset) +{ + unsigned int i; + fprintf(stderr, "%s: %s\n", message, buffer); + for (i = 0; i < strlen(message) + 2; i++) + fprintf(stderr, " "); + for (i = 0; i < offset; i++) + fprintf(stderr, " "); + fprintf(stderr, "^\n"); +} static int parse_boot_order(char *buffer, uint16_t **order, size_t *length) { - int i, len; - int num, rc; - uint16_t *data; size_t data_size; - - len = strlen(buffer); - if (len % 5 != 4) { - fprintf(stderr, "\nInvalid boot order: %s\n\n", buffer); - return -1; + size_t len = strlen(buffer); + intptr_t end = (intptr_t)buffer + len + 1; + + int num = 0; + char *buf = buffer; + while ((intptr_t)buf < end) { + size_t comma = strcspn(buf, ","); + if (comma == 0) { + off_t offset = (intptr_t)buf - (intptr_t)buffer; + print_error_arrow("Malformed boot order",buffer,offset); + exit(8); + } else { + num++; + } + buf += comma + 1; } - len = (len / 5) + 1; - data_size = len * sizeof (*data); - data = malloc(data_size); + data = calloc(num, sizeof (*data)); if (!data) return -1; - - for (i=0; i < len && *buffer; i++) { - rc = sscanf(buffer, "%x", &num); - if (rc == 1) { - data[i] = num & 0xFFFF; - } else { - fprintf(stderr,"\nInvalid hex characters in boot order: %s\n\n",buffer); + data_size = num * sizeof (*data); + + int i = 0; + buf = buffer; + while ((intptr_t)buf < end) { + unsigned long result = 0; + size_t comma = strcspn(buf, ","); + + buf[comma] = '\0'; + char *endptr = NULL; + result = strtoul(buf, &endptr, 16); + if ((result == ULONG_MAX && errno == ERANGE) || + (endptr && *endptr != '\0')) { + print_error_arrow("Invalid boot order", buffer, + (intptr_t)endptr - (intptr_t)buffer); free(data); - return -1; + exit(8); } + if (result > 0xffff) { + fprintf(stderr, "Invalid boot order entry value: %lX\n", + result); + print_error_arrow("Invalid boot order", buffer, + (intptr_t)buf - (intptr_t)buffer); + free(data); + exit(8); + } + /* make sure this is an existing boot entry */ - if (!is_current_boot_entry(data[i])) { - fprintf (stderr,"\nboot entry %X does not exist\n\n",data[i]); + if (!is_current_boot_entry(result)) { + print_error_arrow("Invalid boot order entry value", + buffer, + (intptr_t)buf - (intptr_t)buffer); + fprintf(stderr,"Boot entry %04lX does not exist\n", + result); free(data); - return -1; + exit(8); } - /* Advance to the comma */ - while (*buffer && *buffer != ',') buffer++; - /* Advance through the comma(s) */ - while (*buffer && *buffer == ',') buffer++; + data[i++] = result; + buf[comma] = ','; + buf += comma + 1; } + *order = data; *length = data_size; - return i; + return num; } static int -- 2.7.4