]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Avoid cutting in the middle of UTF-8 string.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 25 Dec 2011 15:11:41 +0000 (16:11 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 25 Dec 2011 15:11:41 +0000 (16:11 +0100)
* 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.

ChangeLog
grub-core/normal/completion.c
grub-core/script/function.c
include/grub/charset.h

index 4559ffe49d4ee7dc23f60738ba5532d2c906479f..ba142a6eb3d828230d273c232474e16352f57977 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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.
index 8568cd892d34e42716e5b3646092ff57ca1aaa00..f4dab533b2768a5335452db13b356ae005473716 100644 (file)
@@ -26,6 +26,7 @@
 #include <grub/file.h>
 #include <grub/parser.h>
 #include <grub/extcmd.h>
+#include <grub/charset.h>
 
 /* 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';
          }
index 47b236652af8541a5542bb554c72e1b728f40d77..ae924011660e6dbb773bfafed208daf9cc33b5a6 100644 (file)
@@ -20,6 +20,7 @@
 #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;
 
@@ -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;
 }
index 82a005f32d97cf1a10bf8c1ba9eb1294b18e5c1e..4f9e8099f5c8f9275ae695bdfaf84e4c42ed250f 100644 (file)
@@ -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,