From 2929a0053a56e1d3b0bed26f16a1e1ad83141891 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Thu, 1 Sep 2011 18:17:27 -0700 Subject: [PATCH] hivex: Split value_key function into value_key and value_key_len This function breaks the value name calculation out so the name does not need to be fetched and immediately thrown away when one only needs the name. Signed-off-by: Alex Nelson RWMJ fixed hivex_value_key handling of errno. --- generator/generator.ml | 11 +++++++++++ lib/hivex.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/generator/generator.ml b/generator/generator.ml index b880b48..6f318ac 100755 --- a/generator/generator.ml +++ b/generator/generator.ml @@ -229,6 +229,17 @@ string C<\"\"> here. The default key is often written C<\"@\">, but inside hives that has no meaning and won't give you the default key."; + "value_key_len", (RSize, [AHive; AValue "val"]), + "return the length of a value's key", + "\ +Return the length of the key (name) of a (key, value) pair. The +length can legitimately be 0, so errno is the necesary mechanism +to check for errors. + +In the context of Windows Registries, a zero-length name means +that this value is the default key for this node in the tree. +This is usually written as C<\"@\">."; + "value_key", (RString, [AHive; AValue "val"]), "return the key of a (key, value) pair", "\ diff --git a/lib/hivex.c b/lib/hivex.c index 4b9fcf0..a183527 100644 --- a/lib/hivex.c +++ b/lib/hivex.c @@ -1189,8 +1189,8 @@ 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_key_len (hive_h *h, hive_value_h value) { if (!IS_VALID_BLOCK (h, value) || !BLOCK_ID_EQ (h, value, "vk")) { errno = EINVAL; @@ -1199,23 +1199,39 @@ 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) -- 1.8.3.1