summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorVaclav Dolezal2017-09-20 15:50:37 +0200
committerVaclav Dolezal2017-12-18 16:17:49 +0100
commit5be3df4afd7adf8b71edee18625d6e35b23a6152 (patch)
treea926a48006f49acb4d68b62a5779cf7d7bcff19b /libfdisk
parentlib/mbsalign: encode backslash to prevent ambiguity (diff)
downloadkernel-qcow2-util-linux-5be3df4afd7adf8b71edee18625d6e35b23a6152.tar.gz
kernel-qcow2-util-linux-5be3df4afd7adf8b71edee18625d6e35b23a6152.tar.xz
kernel-qcow2-util-linux-5be3df4afd7adf8b71edee18625d6e35b23a6152.zip
libfdisk: gpt: properly encode string on rename
GPT partition name entry should be recorded as little endian UCS2, so I have written proper conversion (assuming UTF8 input). Signed-off-by: Vaclav Dolezal <vdolezal@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/src/gpt.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 56bd373cd..d77ed2d2b 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -382,19 +382,45 @@ static void gpt_entry_set_type(struct gpt_entry *e, struct gpt_guid *uuid)
DBG(LABEL, gpt_debug_uuid("new type", uuid));
}
-static void gpt_entry_set_name(struct gpt_entry *e, char *str)
-{
- char name[GPT_PART_NAME_LEN] = { 0 };
- size_t i, sz = strlen(str);
-
- if (sz) {
- if (sz > GPT_PART_NAME_LEN)
- sz = GPT_PART_NAME_LEN;
- memcpy(name, str, sz);
+static int gpt_entry_set_name(struct gpt_entry *e, char *str)
+{
+ uint16_t name[GPT_PART_NAME_LEN] = { 0 };
+ size_t i, mblen = 0;
+ uint8_t *in = (uint8_t *) str;
+
+ for (i = 0; *in && i < GPT_PART_NAME_LEN; in++) {
+ if (!mblen) {
+ if (!(*in & 0x80)) {
+ name[i++] = *in;
+ } else if ((*in & 0xE0) == 0xC0) {
+ mblen = 1;
+ name[i] = (uint16_t)(*in & 0x1F) << (mblen *6);
+ } else if ((*in & 0xF0) == 0xE0) {
+ mblen = 2;
+ name[i] = (uint16_t)(*in & 0x0F) << (mblen *6);
+ } else {
+ /* broken UTF-8 or code point greater than U+FFFF */
+ return -EILSEQ;
+ }
+ } else {
+ /* incomplete UTF-8 sequence */
+ if ((*in & 0xC0) != 0x80)
+ return -EILSEQ;
+
+ name[i] |= (uint16_t)(*in & 0x3F) << (--mblen *6);
+ if (!mblen) {
+ /* check for code points reserved for surrogate pairs*/
+ if ((name[i] & 0xF800) == 0xD800)
+ return -EILSEQ;
+ i++;
+ }
+ }
}
for (i = 0; i < GPT_PART_NAME_LEN; i++)
- e->name[i] = cpu_to_le16((uint16_t) name[i]);
+ e->name[i] = cpu_to_le16(name[i]);
+
+ return 0;
}
static int gpt_entry_set_uuid(struct gpt_entry *e, char *str)