kern/misc, kern/efi: Extract UTF-8 to UTF-16 code
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>
This commit is contained in:
parent
389d3dc835
commit
a0b16564ee
@ -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;
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user