]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
kern/misc, kern/efi: Extract UTF-8 to UTF-16 code
authorOliver Steffen <osteffen@redhat.com>
Fri, 26 May 2023 11:35:47 +0000 (13:35 +0200)
committerDaniel Kiper <daniel.kiper@oracle.com>
Thu, 1 Jun 2023 09:45:00 +0000 (11:45 +0200)
Create a new function for UTF-8 to UTF-16 conversion called
grub_utf8_to_utf16_alloc() in the grub-code/kern/misc.c and replace
charset conversion code used in some places in the EFI code. It is
modeled after the grub_utf8_to_ucs4_alloc() like functions in
include/grub/charset.h. It can't live in include/grub/charset.h,
because it needs to be reachable from the kern/efi code.

Add a check for integer overflow and remove redundant NUL-termination.

Signed-off-by: Oliver Steffen <osteffen@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/kern/efi/efi.c
grub-core/kern/misc.c
include/grub/misc.h

index 7d674d074993c7eab30238c6b34382ee21c66528..bd3b125a4e595361ec4f61e850f41b166bdd2594 100644 (file)
@@ -209,15 +209,11 @@ grub_efi_set_variable_with_attributes (const char *var, const grub_guid_t *guid,
   grub_efi_status_t status;
   grub_efi_runtime_services_t *r;
   grub_efi_char16_t *var16;
-  grub_size_t len, len16;
 
-  len = grub_strlen (var);
-  len16 = len * GRUB_MAX_UTF16_PER_UTF8;
-  var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
-  if (!var16)
+  grub_utf8_to_utf16_alloc (var, &var16, NULL);
+
+  if (var16 == NULL)
     return grub_errno;
-  len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
-  var16[len16] = 0;
 
   r = grub_efi_system_table->runtime_services;
 
@@ -251,18 +247,13 @@ grub_efi_get_variable_with_attributes (const char *var,
   grub_efi_runtime_services_t *r;
   grub_efi_char16_t *var16;
   void *data;
-  grub_size_t len, len16;
 
   *data_out = NULL;
   *datasize_out = 0;
 
-  len = grub_strlen (var);
-  len16 = len * GRUB_MAX_UTF16_PER_UTF8;
-  var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
-  if (!var16)
-    return GRUB_EFI_OUT_OF_RESOURCES;
-  len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
-  var16[len16] = 0;
+  grub_utf8_to_utf16_alloc (var, &var16, NULL);
+  if (var16 == NULL)
+    return grub_errno;
 
   r = grub_efi_system_table->runtime_services;
 
index 22b7dca42f2e95683890a0c9df18daf971c6b187..977535282a339a77adff908737a25c4731c50b5a 100644 (file)
@@ -25,6 +25,7 @@
 #include <grub/env.h>
 #include <grub/i18n.h>
 #include <grub/types.h>
+#include <grub/charset.h>
 
 union printf_arg
 {
@@ -1318,6 +1319,37 @@ grub_fatal (const char *fmt, ...)
   grub_abort ();
 }
 
+grub_ssize_t
+grub_utf8_to_utf16_alloc (const char *str8, grub_uint16_t **utf16_msg, grub_uint16_t **last_position)
+{
+  grub_size_t len;
+  grub_size_t len16;
+
+  len = grub_strlen (str8);
+
+  /* Check for integer overflow */
+  if (len > GRUB_SSIZE_MAX / GRUB_MAX_UTF16_PER_UTF8 - 1)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("string too long"));
+      *utf16_msg = NULL;
+      return -1;
+    }
+
+  len16 = len * GRUB_MAX_UTF16_PER_UTF8;
+
+  *utf16_msg = grub_calloc (len16 + 1, sizeof (*utf16_msg[0]));
+  if (*utf16_msg == NULL)
+    return -1;
+
+  len16 = grub_utf8_to_utf16 (*utf16_msg, len16, (grub_uint8_t *) str8, len, NULL);
+
+  if (last_position != NULL)
+    *last_position = *utf16_msg + len16;
+
+  return len16;
+}
+
+
 #if BOOT_TIME_STATS
 
 #include <grub/time.h>
index 6c9d56de9264ff208e527be82032578b5500b9c2..1b35a167fdec92a5eff7f75a57f03b0bbe07c498 100644 (file)
@@ -529,4 +529,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 
 #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1)
 
+grub_ssize_t
+EXPORT_FUNC(grub_utf8_to_utf16_alloc) (const char *str8, grub_uint16_t **utf16_msg, grub_uint16_t **last_position);
+
 #endif /* ! GRUB_MISC_HEADER */