* 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 <phcoder@gmail.com>
+
+ 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 <phcoder@gmail.com>
* grub-core/normal/charset.c (grub_ucs4_to_utf8): Small stylistic fix.
#include <grub/file.h>
#include <grub/parser.h>
#include <grub/extcmd.h>
+#include <grub/charset.h>
/* The current word. */
static const char *current_word;
s++;
t++;
}
+ s = match + grub_getend (match, s);
*s = '\0';
}
#include <grub/script_sh.h>
#include <grub/parser.h>
#include <grub/mm.h>
+#include <grub/charset.h>
grub_script_function_t grub_script_function_list;
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;
}
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,