Don't try to process junk after a string value as UTF-16.
authorRichard Jones <rjones@redhat.com>
Mon, 12 Jul 2010 14:06:35 +0000 (15:06 +0100)
committerRichard Jones <rjones@redhat.com>
Mon, 12 Jul 2010 14:07:12 +0000 (15:07 +0100)
Thanks to Hilko Bengen for characterizing the issue and
providing an initial version of this patch.

lib/hivex.c

index 2b22924..13d7556 100644 (file)
@@ -62,6 +62,8 @@
 #define HIVEX_MAX_ALLOCATION  1000000
 
 static char *windows_utf16_to_utf8 (/* const */ char *input, size_t len);
+static size_t utf16_string_len_in_bytes (const char *str);
+static size_t utf16_string_len_in_bytes_max (const char *str, size_t len);
 
 struct hive_h {
   char *filename;
@@ -1319,6 +1321,20 @@ hivex_value_string (hive_h *h, hive_value_h value)
     return NULL;
   }
 
+  /* Deal with the case where Windows has allocated a large buffer
+   * full of random junk, and only the first few bytes of the buffer
+   * contain a genuine UTF-16 string.
+   *
+   * In this case, iconv would try to process the junk bytes as UTF-16
+   * and inevitably find an illegal sequence (EILSEQ).  Instead, stop
+   * after we find the first \0\0.
+   *
+   * (Found by Hilko Bengen in a fresh Windows XP SOFTWARE hive).
+   */
+  size_t slen = utf16_string_len_in_bytes_max (data, len);
+  if (slen > len)
+    len = slen;
+
   char *ret = windows_utf16_to_utf8 (data, len);
   free (data);
   if (ret == NULL)
@@ -1355,6 +1371,21 @@ utf16_string_len_in_bytes (const char *str)
   return ret;
 }
 
+/* As for utf16_string_len_in_bytes but only read up to a maximum length. */
+static size_t
+utf16_string_len_in_bytes_max (const char *str, size_t len)
+{
+  size_t ret = 0;
+
+  while (len > 0 && (str[0] || str[1])) {
+    str += 2;
+    ret += 2;
+    len -= 2;
+  }
+
+  return ret;
+}
+
 /* http://blogs.msdn.com/oldnewthing/archive/2009/10/08/9904646.aspx */
 char **
 hivex_value_multiple_strings (hive_h *h, hive_value_h value)