From: Vladimir 'phcoder' Serbinenko Date: Sun, 25 Dec 2011 15:11:41 +0000 (+0100) Subject: Avoid cutting in the middle of UTF-8 string. X-Git-Tag: 2.00~819 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d8c47653609470fb177d1115c1d540332baf71a;p=thirdparty%2Fgrub.git Avoid cutting in the middle of UTF-8 string. * include/grub/charset.h (grub_getend): New function. * grub-core/script/function.c (grub_script_function_find): Use grub_getend. * grub-core/normal/completion.c (add_completion): Likewise. --- diff --git a/ChangeLog b/ChangeLog index 4559ffe49..ba142a6eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-25 Vladimir Serbinenko + + Avoid cutting in the middle of UTF-8 string. + + * include/grub/charset.h (grub_getend): New function. + * grub-core/script/function.c (grub_script_function_find): Use + grub_getend. + * grub-core/normal/completion.c (add_completion): Likewise. + 2011-12-25 Vladimir Serbinenko * grub-core/normal/charset.c (grub_ucs4_to_utf8): Small stylistic fix. diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index 8568cd892..f4dab533b 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -26,6 +26,7 @@ #include #include #include +#include /* The current word. */ static const char *current_word; @@ -86,6 +87,7 @@ add_completion (const char *completion, const char *extra, s++; t++; } + s = match + grub_getend (match, s); *s = '\0'; } diff --git a/grub-core/script/function.c b/grub-core/script/function.c index 47b236652..ae9240116 100644 --- a/grub-core/script/function.c +++ b/grub-core/script/function.c @@ -20,6 +20,7 @@ #include #include #include +#include grub_script_function_t grub_script_function_list; @@ -99,7 +100,14 @@ grub_script_function_find (char *functionname) break; if (! func) - grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%.20s'", functionname); + { + char tmp[21]; + grub_strncpy (tmp, functionname, 20); + tmp[20] = 0; + /* Avoid truncating inside UTF-8 character. */ + tmp[grub_getend (tmp, tmp + grub_strlen (tmp))] = 0; + grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", tmp); + } return func; } diff --git a/include/grub/charset.h b/include/grub/charset.h index 82a005f32..4f9e8099f 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -49,6 +49,32 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend); +/* Determine the last position where the UTF-8 string [beg, end) can + be safely cut. */ +static inline grub_size_t +grub_getend (const char *beg, const char *end) +{ + const char *ptr; + for (ptr = end - 1; ptr >= beg; ptr--) + if ((*ptr & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) + break; + if (ptr < beg) + return 0; + if ((*ptr & GRUB_UINT8_1_LEADINGBIT) == 0) + return ptr + 1 - beg; + if ((*ptr & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS + && ptr + 2 <= end) + return ptr + 2 - beg; + if ((*ptr & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS + && ptr + 3 <= end) + return ptr + 3 - beg; + if ((*ptr & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS + && ptr + 4 <= end) + return ptr + 4 - beg; + /* Invalid character or incomplete. Cut before it. */ + return ptr - beg; +} + /* Convert UTF-16 to UTF-8. */ static inline grub_uint8_t * grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src,