#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;
{
int r;
+ if (h->msglvl >= 1)
+ fprintf (stderr, "hivex_close\n");
+
free (h->bitmap);
if (!h->writable)
munmap (h->addr, h->size);
fprintf (stderr, "hivex_value_value: warning: declared data length is longer than the block it is in (data 0x%zx, data len %zu, block len %zu)\n",
data_offset, len, blen);
len = blen - 4;
+
+ /* Return the smaller length to the caller too. */
+ if (len_rtn)
+ *len_rtn = len;
}
char *data = h->addr + data_offset + 4;
size_t r = iconv (ic, &inp, &inlen, &outp, &outlen);
if (r == (size_t) -1) {
if (errno == E2BIG) {
+ int err = errno;
size_t prev = outalloc;
/* Try again with a larger output buffer. */
free (out);
outalloc *= 2;
- if (outalloc < prev)
+ if (outalloc < prev) {
+ iconv_close (ic);
+ errno = err;
return NULL;
+ }
goto again;
}
else {
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)
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 >= 2 && (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)