X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fhivex.c;h=3063c456f9fddd2e425cce809c39acff9f12c0a3;hb=e85b1eaa268caea316f6aa8e02738b3d94297250;hp=4b9fcf0512a80a1184417ce9ed541fae9b3440d3;hpb=24e778286a2d684cb08afb29f5c0e48b2b312e7e;p=hivex.git diff --git a/lib/hivex.c b/lib/hivex.c index 4b9fcf0..3063c45 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -585,6 +585,30 @@ hivex_root (hive_h *h) return ret; } +size_t +hivex_node_struct_length (hive_h *h, hive_node_h node) +{ + if (!IS_VALID_BLOCK (h, node) || !BLOCK_ID_EQ (h, node, "nk")) { + errno = EINVAL; + return 0; + } + + struct ntreg_nk_record *nk = (struct ntreg_nk_record *) (h->addr + node); + size_t name_len = le16toh (nk->name_len); + /* -1 to avoid double-counting the first name character */ + size_t ret = name_len + sizeof (struct ntreg_nk_record) - 1; + int used; + size_t seg_len = block_len (h, node, &used); + if (ret > seg_len) { + if (h->msglvl >= 2) + fprintf (stderr, "hivex_node_struct_length: returning EFAULT because" + " node name is too long (%zu, %zu)\n", name_len, seg_len); + errno = EFAULT; + return 0; + } + return ret; +} + char * hivex_node_name (hive_h *h, hive_node_h node) { @@ -1189,8 +1213,22 @@ hivex_node_get_value (hive_h *h, hive_node_h node, const char *key) return ret; } -char * -hivex_value_key (hive_h *h, hive_value_h value) +size_t +hivex_value_struct_length (hive_h *h, hive_value_h value) +{ + size_t key_len; + + errno = 0; + key_len = hivex_value_key_len (h, value); + if (key_len == 0 && errno != 0) + return 0; + + /* -1 to avoid double-counting the first name character */ + return key_len + sizeof (struct ntreg_vk_record) - 1; +} + +size_t +hivex_value_key_len (hive_h *h, hive_value_h value) { if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) { errno = EINVAL; @@ -1199,24 +1237,40 @@ hivex_value_key (hive_h *h, hive_value_h value) struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value); - /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is - * necessary. However we do need to nul-terminate the string. - */ - /* vk->name_len is unsigned, 16 bit, so this is safe ... However * we have to make sure the length doesn't exceed the block length. */ - size_t len = le16toh (vk->name_len); + size_t ret = le16toh (vk->name_len); size_t seg_len = block_len (h, value, NULL); - if (sizeof (struct ntreg_vk_record) + len - 1 > seg_len) { + if (sizeof (struct ntreg_vk_record) + ret - 1 > seg_len) { if (h->msglvl >= 2) - fprintf (stderr, "hivex_value_key: returning EFAULT" + fprintf (stderr, "hivex_value_key_len: returning EFAULT" " because key length is too long (%zu, %zu)\n", - len, seg_len); + ret, seg_len); errno = EFAULT; - return NULL; + return 0; + } + return ret; +} + +char * +hivex_value_key (hive_h *h, hive_value_h value) +{ + if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) { + errno = EINVAL; + return 0; } + struct ntreg_vk_record *vk = (struct ntreg_vk_record *) (h->addr + value); + + /* AFAIK the key is always plain ASCII, so no conversion to UTF-8 is + * necessary. However we do need to nul-terminate the string. + */ + errno = 0; + size_t len = hivex_value_key_len (h, value); + if (len == 0 && errno != 0) + return NULL; + char *ret = malloc (len + 1); if (ret == NULL) return NULL;