}
/* Iterate over children, returning child nodes and intermediate blocks. */
+#define GET_CHILDREN_NO_CHECK_NK 1
+
static int
get_children (hive_h *h, hive_node_h node,
- hive_node_h **children_ret, size_t **blocks_ret)
+ hive_node_h **children_ret, size_t **blocks_ret,
+ int flags)
{
if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) {
errno = EINVAL;
for (i = 0; i < nr_subkeys_in_lf; ++i) {
hive_node_h subkey = le32toh (lf->keys[i].offset);
subkey += 0x1000;
- if (!IS_VALID_BLOCK (h, subkey)) {
- if (h->msglvl >= 2)
- fprintf (stderr, "hivex_node_children: returning EFAULT because subkey is not a valid block (0x%zx)\n",
- subkey);
- errno = EFAULT;
- goto error;
+ if (!(flags & GET_CHILDREN_NO_CHECK_NK)) {
+ if (!IS_VALID_BLOCK (h, subkey)) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_node_children: returning EFAULT because subkey is not a valid block (0x%zx)\n",
+ subkey);
+ errno = EFAULT;
+ goto error;
+ }
}
if (add_to_offset_list (&children, subkey) == -1)
goto error;
for (j = 0; j < le16toh (lf->nr_keys); ++j) {
hive_node_h subkey = le32toh (lf->keys[j].offset);
subkey += 0x1000;
- if (!IS_VALID_BLOCK (h, subkey)) {
- if (h->msglvl >= 2)
- fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (0x%zx)\n",
- subkey);
- errno = EFAULT;
- goto error;
+ if (!(flags & GET_CHILDREN_NO_CHECK_NK)) {
+ if (!IS_VALID_BLOCK (h, subkey)) {
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_node_children: returning EFAULT because indirect subkey is not a valid block (0x%zx)\n",
+ subkey);
+ errno = EFAULT;
+ goto error;
+ }
}
if (add_to_offset_list (&children, subkey) == -1)
goto error;
hive_node_h *children;
size_t *blocks;
- if (get_children (h, node, &children, &blocks) == -1)
+ if (get_children (h, node, &children, &blocks, 0) == -1)
return NULL;
free (blocks);
return NULL;
}
- /* Check that the declared size isn't larger than the block its in. */
+ /* Check that the declared size isn't larger than the block its in.
+ *
+ * XXX Some apparently valid registries are seen to have this,
+ * so turn this into a warning and substitute the smaller length
+ * instead.
+ */
size_t blen = block_len (h, data_offset, NULL);
if (len > blen - 4 /* subtract 4 for block header */) {
if (h->msglvl >= 2)
- fprintf (stderr, "hivex_value_value: returning EFAULT because data is longer than its block (data 0x%zx, data len %zu, block len %zu)\n",
+ 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);
- errno = EFAULT;
- free (ret);
- return NULL;
+ len = blen - 4;
}
char *data = h->addr + data_offset + 4;