diff options
author | Vaclav Dolezal | 2017-09-20 15:50:37 +0200 |
---|---|---|
committer | Vaclav Dolezal | 2017-12-18 16:17:49 +0100 |
commit | 5be3df4afd7adf8b71edee18625d6e35b23a6152 (patch) | |
tree | a926a48006f49acb4d68b62a5779cf7d7bcff19b /libfdisk | |
parent | lib/mbsalign: encode backslash to prevent ambiguity (diff) | |
download | kernel-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.c | 46 |
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) |