Blame SOURCES/0023-Make-o-s-behavior-actually-match-the-documented-beha.patch

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