X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=hivex%2Fhivex.c;h=36c6b0eb494e3b5996cc743cebdba4760adc18bb;hp=a0a730cdb7db89afbd33d0ea8e8bbf23115f8e47;hb=0221c671e4ce572c602f8576e82f89b4c02c6232;hpb=d707ecc55ac2de267608435bdc1052176aecff46 diff --git a/hivex/hivex.c b/hivex/hivex.c index a0a730c..36c6b0e 100644 --- a/hivex/hivex.c +++ b/hivex/hivex.c @@ -30,7 +30,6 @@ #include #include #include -#include #ifdef HAVE_ENDIAN_H #include #endif @@ -38,6 +37,16 @@ #include #endif +#define STREQ(a,b) (strcmp((a),(b)) == 0) +#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0) +//#define STRNEQ(a,b) (strcmp((a),(b)) != 0) +//#define STRCASENEQ(a,b) (strcasecmp((a),(b)) != 0) +#define STREQLEN(a,b,n) (strncmp((a),(b),(n)) == 0) +//#define STRCASEEQLEN(a,b,n) (strncasecmp((a),(b),(n)) == 0) +//#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0) +//#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0) +//#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0) + #if __BYTE_ORDER == __LITTLE_ENDIAN #ifndef be32toh #define be32toh(x) __bswap_32 (x) @@ -46,13 +55,13 @@ #define be64toh(x) __bswap_64 (x) #endif #ifndef le16toh -#define le32toh(x) (x) +#define le16toh(x) (x) #endif #ifndef le32toh #define le32toh(x) (x) #endif #ifndef le64toh -#define le32toh(x) (x) +#define le64toh(x) (x) #endif #else #ifndef be32toh @@ -96,7 +105,7 @@ struct hive_h { #define BITMAP_SET(bitmap,off) (bitmap[(off)>>5] |= 1 << (((off)>>2)&7)) #define BITMAP_CLR(bitmap,off) (bitmap[(off)>>5] &= ~ (1 << (((off)>>2)&7))) #define BITMAP_TST(bitmap,off) (bitmap[(off)>>5] & (1 << (((off)>>2)&7))) -#define IS_VALID_BLOCK(h,off) \ +#define IS_VALID_BLOCK(h,off) \ (((off) & 3) == 0 && \ (off) >= 0x1000 && \ (off) < (h)->size && \ @@ -144,7 +153,7 @@ struct ntreg_hbin_block { } __attribute__((__packed__)); #define BLOCK_ID_EQ(h,offs,eqid) \ - (strncmp (((struct ntreg_hbin_block *)((h)->addr + (offs)))->id, (eqid), 2) == 0) + (STREQLEN (((struct ntreg_hbin_block *)((h)->addr + (offs)))->id, (eqid), 2)) static size_t block_len (hive_h *h, size_t blkoff, int *used) @@ -236,11 +245,11 @@ hivex_open (const char *filename, int flags) h->msglvl = flags & HIVEX_OPEN_MSGLVL_MASK; const char *debug = getenv ("HIVEX_DEBUG"); - if (debug && strcmp (debug, "1") == 0) + if (debug && STREQ (debug, "1")) h->msglvl = 2; if (h->msglvl >= 2) - printf ("hivex_open: created handle %p\n", h); + fprintf (stderr, "hivex_open: created handle %p\n", h); h->fd = open (filename, O_RDONLY); if (h->fd == -1) @@ -257,7 +266,7 @@ hivex_open (const char *filename, int flags) goto error; if (h->msglvl >= 2) - printf ("hivex_open: mapped file at %p\n", h->addr); + fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr); /* Check header. */ if (h->hdr->magic[0] != 'r' || @@ -271,6 +280,8 @@ hivex_open (const char *filename, int flags) } h->bitmap = calloc (1 + h->size / 32, 1); + if (h->bitmap == NULL) + goto error; #if 0 /* Doesn't work. */ /* Header checksum. */ @@ -291,7 +302,7 @@ hivex_open (const char *filename, int flags) h->rootoffs = le32toh (h->hdr->offset) + 0x1000; if (h->msglvl >= 2) - printf ("hivex_open: root offset = %zu\n", h->rootoffs); + fprintf (stderr, "hivex_open: root offset = %zu\n", h->rootoffs); /* We'll set this flag when we see a block with the root offset (ie. * the root block). @@ -314,16 +325,15 @@ hivex_open (const char *filename, int flags) page->magic[1] != 'b' || page->magic[2] != 'i' || page->magic[3] != 'n') { - /* This error is seemingly common in uncorrupt registry files. */ - /* - fprintf (stderr, "hivex: %s: ignoring trailing garbage at end of file (at %zu, after %zu pages)\n", - filename, off, h->pages); - */ + /* NB: This error is seemingly common in uncorrupt registry files. */ + if (h->msglvl >= 2) + fprintf (stderr, "hivex: %s: ignoring trailing garbage at end of file (at %zu, after %zu pages)\n", + filename, off, h->pages); break; } if (h->msglvl >= 2) - printf ("hivex_open: page at %zu\n", off); + fprintf (stderr, "hivex_open: page at %zu\n", off); if (le32toh (page->offset_next) <= sizeof (struct ntreg_hbin_page) || (le32toh (page->offset_next) & 3) != 0) { @@ -357,9 +367,9 @@ hivex_open (const char *filename, int flags) } if (h->msglvl >= 2) - printf ("hivex_open: %s block id %d,%d at %zu%s\n", - used ? "used" : "free", block->id[0], block->id[1], blkoff, - is_root ? " (root)" : ""); + fprintf (stderr, "hivex_open: %s block id %d,%d at %zu%s\n", + used ? "used" : "free", block->id[0], block->id[1], blkoff, + is_root ? " (root)" : ""); if (is_root && !used) bad_root_block = 1; @@ -391,12 +401,13 @@ hivex_open (const char *filename, int flags) } if (h->msglvl >= 1) - printf ("hivex_open: successfully read Windows Registry hive file:\n" - " pages: %zu\n" - " blocks: %zu\n" - " blocks used: %zu\n" - " bytes used: %zu\n", - h->pages, h->blocks, h->used_blocks, h->used_size); + fprintf (stderr, + "hivex_open: successfully read Windows Registry hive file:\n" + " pages: %zu\n" + " blocks: %zu\n" + " blocks used: %zu\n" + " bytes used: %zu\n", + h->pages, h->blocks, h->used_blocks, h->used_size); return h; @@ -460,7 +471,7 @@ hivex_node_name (hive_h *h, hive_node_h node) size_t seg_len = block_len (h, node, NULL); if (sizeof (struct ntreg_nk_record) + len - 1 > seg_len) { if (h->msglvl >= 2) - printf ("hivex_node_name: returning EFAULT because node name is too long (%zu, %zu)\n", + fprintf (stderr, "hivex_node_name: returning EFAULT because node name is too long (%zu, %zu)\n", len, seg_len); errno = EFAULT; return NULL; @@ -556,8 +567,8 @@ hivex_node_children (hive_h *h, hive_node_h node) subkey_lf += 0x1000; if (!IS_VALID_BLOCK (h, subkey_lf)) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because subkey_lf is not a valid block (%zu)\n", - subkey_lf); + fprintf (stderr, "hivex_node_children: returning EFAULT because subkey_lf is not a valid block (%zu)\n", + subkey_lf); errno = EFAULT; return NULL; } @@ -577,8 +588,8 @@ hivex_node_children (hive_h *h, hive_node_h node) size_t nr_subkeys_in_lf = le16toh (lf->nr_keys); if (h->msglvl >= 2) - printf ("hivex_node_children: nr_subkeys_in_nk = %zu, nr_subkeys_in_lf = %zu\n", - nr_subkeys_in_nk, nr_subkeys_in_lf); + fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, nr_subkeys_in_lf = %zu\n", + nr_subkeys_in_nk, nr_subkeys_in_lf); if (nr_subkeys_in_nk != nr_subkeys_in_lf) { errno = ENOTSUP; @@ -588,8 +599,8 @@ hivex_node_children (hive_h *h, hive_node_h node) size_t len = block_len (h, subkey_lf, NULL); if (8 + nr_subkeys_in_lf * 8 > len) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because too many subkeys (%zu, %zu)\n", - nr_subkeys_in_lf, len); + fprintf (stderr, "hivex_node_children: returning EFAULT because too many subkeys (%zu, %zu)\n", + nr_subkeys_in_lf, len); errno = EFAULT; return NULL; } @@ -607,8 +618,8 @@ hivex_node_children (hive_h *h, hive_node_h node) subkey += 0x1000; if (!IS_VALID_BLOCK (h, subkey)) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because subkey is not a valid block (%zu)\n", - subkey); + fprintf (stderr, "hivex_node_children: returning EFAULT because subkey is not a valid block (%zu)\n", + subkey); errno = EFAULT; free (ret); return NULL; @@ -631,8 +642,8 @@ hivex_node_children (hive_h *h, hive_node_h node) offset += 0x1000; if (!IS_VALID_BLOCK (h, offset)) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n", - offset); + fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n", + offset); errno = EFAULT; return NULL; } @@ -648,8 +659,8 @@ hivex_node_children (hive_h *h, hive_node_h node) } if (h->msglvl >= 2) - printf ("hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n", - nr_subkeys_in_nk, count); + fprintf (stderr, "hivex_node_children: nr_subkeys_in_nk = %zu, counted = %zu\n", + nr_subkeys_in_nk, count); if (nr_subkeys_in_nk != count) { errno = ENOTSUP; @@ -669,8 +680,8 @@ hivex_node_children (hive_h *h, hive_node_h node) offset += 0x1000; if (!IS_VALID_BLOCK (h, offset)) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n", - offset); + fprintf (stderr, "hivex_node_children: returning EFAULT because ri-offset is not a valid block (%zu)\n", + offset); errno = EFAULT; return NULL; } @@ -688,8 +699,8 @@ hivex_node_children (hive_h *h, hive_node_h node) subkey += 0x1000; if (!IS_VALID_BLOCK (h, subkey)) { if (h->msglvl >= 2) - printf ("hivex_node_children: returning EFAULT because indirect subkey is not a valid block (%zu)\n", - subkey); + fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (%zu)\n", + subkey); errno = EFAULT; free (ret); return NULL; @@ -724,7 +735,7 @@ hivex_node_get_child (hive_h *h, hive_node_h node, const char *nname) for (i = 0; children[i] != 0; ++i) { name = hivex_node_name (h, children[i]); if (!name) goto error; - if (strcasecmp (name, nname) == 0) { + if (STRCASEEQ (name, nname)) { ret = children[i]; break; } @@ -749,10 +760,9 @@ hivex_node_parent (hive_h *h, hive_node_h node) hive_node_h ret = le32toh (nk->parent); ret += 0x1000; - printf ("parent = %zu\n", ret); if (!IS_VALID_BLOCK (h, ret)) { if (h->msglvl >= 2) - printf ("hivex_node_parent: returning EFAULT because parent is not a valid block (%zu)\n", + fprintf (stderr, "hivex_node_parent: returning EFAULT because parent is not a valid block (%zu)\n", ret); errno = EFAULT; return 0; @@ -773,7 +783,7 @@ hivex_node_values (hive_h *h, hive_node_h node) size_t nr_values = le32toh (nk->nr_values); if (h->msglvl >= 2) - printf ("hivex_node_values: nr_values = %zu\n", nr_values); + fprintf (stderr, "hivex_node_values: nr_values = %zu\n", nr_values); /* Deal with the common "no values" case quickly. */ hive_node_h *ret; @@ -796,8 +806,8 @@ hivex_node_values (hive_h *h, hive_node_h node) vlist_offset += 0x1000; if (!IS_VALID_BLOCK (h, vlist_offset)) { if (h->msglvl >= 2) - printf ("hivex_node_values: returning EFAULT because value list is not a valid block (%zu)\n", - vlist_offset); + fprintf (stderr, "hivex_node_values: returning EFAULT because value list is not a valid block (%zu)\n", + vlist_offset); errno = EFAULT; return NULL; } @@ -808,8 +818,8 @@ hivex_node_values (hive_h *h, hive_node_h node) size_t len = block_len (h, vlist_offset, NULL); if (4 + nr_values * 4 > len) { if (h->msglvl >= 2) - printf ("hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n", - nr_values, len); + fprintf (stderr, "hivex_node_values: returning EFAULT because value list is too long (%zu, %zu)\n", + nr_values, len); errno = EFAULT; return NULL; } @@ -825,8 +835,8 @@ hivex_node_values (hive_h *h, hive_node_h node) value += 0x1000; if (!IS_VALID_BLOCK (h, value)) { if (h->msglvl >= 2) - printf ("hivex_node_values: returning EFAULT because value is not a valid block (%zu)\n", - value); + fprintf (stderr, "hivex_node_values: returning EFAULT because value is not a valid block (%zu)\n", + value); errno = EFAULT; free (ret); return NULL; @@ -855,7 +865,7 @@ hivex_node_get_value (hive_h *h, hive_node_h node, const char *key) for (i = 0; values[i] != 0; ++i) { name = hivex_value_key (h, values[i]); if (!name) goto error; - if (strcasecmp (name, key) == 0) { + if (STRCASEEQ (name, key)) { ret = values[i]; break; } @@ -889,8 +899,8 @@ hivex_value_key (hive_h *h, hive_value_h value) size_t seg_len = block_len (h, value, NULL); if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) { if (h->msglvl >= 2) - printf ("hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n", - len, seg_len); + fprintf (stderr, "hivex_value_key: returning EFAULT because key length is too long (%zu, %zu)\n", + len, seg_len); errno = EFAULT; return NULL; } @@ -952,8 +962,8 @@ hivex_value_value (hive_h *h, hive_value_h value, len &= 0x7fffffff; if (h->msglvl >= 2) - printf ("hivex_value_value: value=%zu, t=%d, len=%zu\n", - value, t, len); + fprintf (stderr, "hivex_value_value: value=%zu, t=%d, len=%zu\n", + value, t, len); if (t_rtn) *t_rtn = t; @@ -980,8 +990,8 @@ hivex_value_value (hive_h *h, hive_value_h value, data_offset += 0x1000; if (!IS_VALID_BLOCK (h, data_offset)) { if (h->msglvl >= 2) - printf ("hivex_value_value: returning EFAULT because data offset is not a valid block (%zu)\n", - data_offset); + fprintf (stderr, "hivex_value_value: returning EFAULT because data offset is not a valid block (%zu)\n", + data_offset); errno = EFAULT; free (ret); return NULL; @@ -991,8 +1001,8 @@ hivex_value_value (hive_h *h, hive_value_h value, size_t blen = block_len (h, data_offset, NULL); if (blen < len) { if (h->msglvl >= 2) - printf ("hivex_value_value: returning EFAULT because data is longer than its block (%zu, %zu)\n", - blen, len); + fprintf (stderr, "hivex_value_value: returning EFAULT because data is longer than its block (%zu, %zu)\n", + blen, len); errno = EFAULT; free (ret); return NULL; @@ -1031,9 +1041,12 @@ windows_utf16_to_utf8 (/* const */ char *input, size_t len) size_t r = iconv (ic, &inp, &inlen, &outp, &outlen); if (r == (size_t) -1) { if (errno == E2BIG) { + size_t prev = outalloc; /* Try again with a larger output buffer. */ free (out); outalloc *= 2; + if (outalloc < prev) + return NULL; goto again; } else { @@ -1261,8 +1274,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, if (!BITMAP_TST (unvisited, node)) { if (h->msglvl >= 2) - printf ("hivex__visit_node: contains cycle: visited node %zu already\n", - node); + fprintf (stderr, "hivex__visit_node: contains cycle: visited node %zu already\n", + node); errno = ELOOP; return skip_bad ? 0 : -1; @@ -1416,8 +1429,8 @@ hivex__visit_node (hive_h *h, hive_node_h node, for (i = 0; children[i] != 0; ++i) { if (h->msglvl >= 2) - printf ("hivex__visit_node: %s: visiting subkey %d (%zu)\n", - name, i, children[i]); + fprintf (stderr, "hivex__visit_node: %s: visiting subkey %d (%zu)\n", + name, i, children[i]); if (hivex__visit_node (h, children[i], vtor, unvisited, opaque, flags) == -1) goto error;