diff options
author | Richard Jones <rjones@redhat.com> | 2010-07-12 15:06:35 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2010-07-12 15:07:12 +0100 |
commit | b71b88f588f8660935a7d462e97b84aa2d669249 (patch) | |
tree | 85d0f2f0f48583e530e9858d1fcaacd840e1368e | |
parent | 374659033e8eeea5b25246a9ef80bee3ebc2cde9 (diff) | |
download | hivex-b71b88f588f8660935a7d462e97b84aa2d669249.tar.gz hivex-b71b88f588f8660935a7d462e97b84aa2d669249.tar.xz hivex-b71b88f588f8660935a7d462e97b84aa2d669249.zip |
Don't try to process junk after a string value as UTF-16.
Thanks to Hilko Bengen for characterizing the issue and
providing an initial version of this patch.
-rw-r--r-- | lib/hivex.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/hivex.c b/lib/hivex.c index 2b22924..13d7556 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -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) |