From 344f26a7664f0a3f1a4b302e08a408171bdc3ece Mon Sep 17 00:00:00 2001
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Date: Sat, 29 Jan 2022 19:01:07 +0100
Subject: [PATCH] efi_loader: fix device path to text protocol

The printing of a file path node must properly handle:

* odd length of the device path node
* UTF-16 character only partially contained in device path node
* buffer overflow due to very long file path

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
---
 lib/efi_loader/efi_device_path_to_text.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index d8a83c8849..97b3d3e815 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <blk.h>
 #include <efi_loader.h>
+#include <malloc.h>
 
 #define MAC_OUTPUT_LEN 22
 #define UNKNOWN_OUTPUT_LEN 23
@@ -292,10 +293,18 @@ static char *dp_media(char *s, struct efi_device_path *dp)
 	case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
 		struct efi_device_path_file_path *fp =
 			(struct efi_device_path_file_path *)dp;
-		int slen = (dp->length - sizeof(*dp)) / 2;
-		if (slen > MAX_NODE_LEN - 2)
-			slen = MAX_NODE_LEN - 2;
-		s += sprintf(s, "%-.*ls", slen, fp->str);
+		u16 *buffer;
+		int slen = dp->length - sizeof(*dp);
+
+		/* two bytes for \0, extra byte if dp->length is odd */
+		buffer = calloc(1, slen + 3);
+		if (!buffer) {
+			log_err("Out of memory\n");
+			return s;
+		}
+		memcpy(buffer, fp->str, dp->length - sizeof(*dp));
+		s += snprintf(s, MAX_NODE_LEN - 1, "%ls", buffer);
+		free(buffer);
 		break;
 	}
 	default:
-- 
2.39.5