From ded09e8ed60d031ad3963dccc1c71800f1d539e1 Mon Sep 17 00:00:00 2001 From: Vaclav Dolezal Date: Fri, 8 Sep 2017 16:36:26 +0200 Subject: [PATCH 1/4] lib/mbsalign: encode backslash to prevent ambiguity Signed-off-by: Vaclav Dolezal --- lib/mbsalign.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mbsalign.c b/lib/mbsalign.c index 78ab12a0d..dce1a1321 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -54,7 +54,7 @@ size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz) last = p + (bufsz - 1); while (p && *p && p <= last) { - if (iscntrl((unsigned char) *p)) { + if (*p == '\\' || iscntrl((unsigned char) *p)) { width += 4, bytes += 4; /* *p encoded to \x?? */ p++; } @@ -135,7 +135,7 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const c continue; } - if (iscntrl((unsigned char) *p)) { + if (*p == '\\' || iscntrl((unsigned char) *p)) { sprintf(r, "\\x%02x", (unsigned char) *p); r += 4; *width += 4; From 5be3df4afd7adf8b71edee18625d6e35b23a6152 Mon Sep 17 00:00:00 2001 From: Vaclav Dolezal Date: Wed, 20 Sep 2017 15:50:37 +0200 Subject: [PATCH 2/4] 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 --- libfdisk/src/gpt.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 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) +static int gpt_entry_set_name(struct gpt_entry *e, char *str) { - char name[GPT_PART_NAME_LEN] = { 0 }; - size_t i, sz = strlen(str); + uint16_t name[GPT_PART_NAME_LEN] = { 0 }; + size_t i, mblen = 0; + uint8_t *in = (uint8_t *) str; - if (sz) { - if (sz > GPT_PART_NAME_LEN) - sz = GPT_PART_NAME_LEN; - memcpy(name, str, sz); + 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) From f069f6fe69dafb6fdd1276237d7719c7b197daa8 Mon Sep 17 00:00:00 2001 From: Vaclav Dolezal Date: Thu, 14 Dec 2017 15:39:42 +0100 Subject: [PATCH 3/4] libfdisk: allocate enough bytes for ucs2 to utf8 encoding Allocate 3*number_of_ucs2_characters bytes for utf8 output. Also as we are using calloc there's no need to write terminating null byte. Signed-off-by: Vaclav Dolezal --- libfdisk/src/gpt.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index d77ed2d2b..8598dbd2e 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -1634,9 +1634,10 @@ static char *encode_to_utf8(unsigned char *src, size_t count) { uint16_t c; char *dest; - size_t i, j, len = count; + size_t i, j; + size_t len = count * 3 / 2; - dest = calloc(1, count); + dest = calloc(1, len + 1); if (!dest) return NULL; @@ -1644,26 +1645,24 @@ static char *encode_to_utf8(unsigned char *src, size_t count) /* always little endian */ c = (src[i+1] << 8) | src[i]; if (c == 0) { - dest[j] = '\0'; break; } else if (c < 0x80) { - if (j+1 >= len) + if (j+1 > len) break; dest[j++] = (uint8_t) c; } else if (c < 0x800) { - if (j+2 >= len) + if (j+2 > len) break; dest[j++] = (uint8_t) (0xc0 | (c >> 6)); dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); } else { - if (j+3 >= len) + if (j+3 > len) break; dest[j++] = (uint8_t) (0xe0 | (c >> 12)); dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); } } - dest[j] = '\0'; return dest; } From c116524184699ed30a823b3994d2e97684bb4505 Mon Sep 17 00:00:00 2001 From: Vaclav Dolezal Date: Tue, 19 Dec 2017 10:39:19 +0100 Subject: [PATCH 4/4] libfdisk: return bytes processed from gpt_entry_set_name(), process rc Made gpt_entry_set_name() return number of utf8 bytes processed on success, so info message about change can be accurate. Signed-off-by: Vaclav Dolezal --- libfdisk/src/gpt.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index 8598dbd2e..543b97199 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -420,7 +420,7 @@ static int gpt_entry_set_name(struct gpt_entry *e, char *str) for (i = 0; i < GPT_PART_NAME_LEN; i++) e->name[i] = cpu_to_le16(name[i]); - return 0; + return (int)((char *) in - str); } static int gpt_entry_set_uuid(struct gpt_entry *e, char *str) @@ -1900,11 +1900,14 @@ static int gpt_set_partition(struct fdisk_context *cxt, size_t n, } if (pa->name) { + int len; char *old = encode_to_utf8((unsigned char *)e->name, sizeof(e->name)); - gpt_entry_set_name(e, pa->name); - - fdisk_info(cxt, _("Partition name changed from '%s' to '%.*s'."), - old, (int) GPT_PART_NAME_LEN, pa->name); + len = gpt_entry_set_name(e, pa->name); + if (len < 0) + fdisk_info(cxt, _("Failed to translate partition name, name not changed.")); + else + fdisk_info(cxt, _("Partition name changed from '%s' to '%.*s'."), + old, len, pa->name); free(old); }