Index: trunk/lib/regfi.c
===================================================================
--- trunk/lib/regfi.c	(revision 113)
+++ trunk/lib/regfi.c	(revision 116)
@@ -442,5 +442,4 @@
 
 /*******************************************************************
- TODO: not currently validating against max_size
  *******************************************************************/
 REGF_HASH_LIST* regfi_load_hashlist(REGF_FILE* file, uint32 offset, 
@@ -463,4 +462,10 @@
 
   ret_val->offset = offset;
+  if(cell_length > max_size)
+  {
+    if(strict)
+      return NULL;
+    cell_length = max_size & 0xFFFFFFF8;
+  }
   ret_val->cell_size = cell_length;
 
@@ -491,8 +496,8 @@
       return NULL;
     }
-    /* TODO: Not sure which should be authoritative, the number from the 
-     *       NK record, or the number in the hash list.  Go with the larger
-     *       of the two to ensure all keys are found.  Note the length checks
-     *       on the cell later ensure that there won't be any critical errors.
+    /* XXX: Not sure which should be authoritative, the number from the 
+     *      NK record, or the number in the hash list.  Go with the larger
+     *      of the two to ensure all keys are found.  Note the length checks
+     *      on the cell later ensure that there won't be any critical errors.
      */
     if(num_keys < ret_val->num_keys)
@@ -565,6 +570,6 @@
 
   ret_val->offset = offset;
-  /* TODO: is there a way to be more conservative (shorter) with 
-   *       cell length when cell is unallocated?
+  /* XXX: Is there a way to be more conservative (shorter) with 
+   *      cell length when cell is unallocated?
    */
   ret_val->cell_size = cell_length;
@@ -582,5 +587,5 @@
   ret_val->magic[1] = sk_header[1];
 
-  /* TODO: can additional validation be added here? */
+  /* XXX: Can additional validation be added here? */
   ret_val->unknown_tag = SVAL(sk_header, 0x2);
   ret_val->prev_sk_off = IVAL(sk_header, 0x4);
@@ -595,5 +600,5 @@
   }
 
-  /* TODO: need to get rid of this, but currently the security descriptor
+  /* XXX: need to get rid of this, but currently the security descriptor
    * code depends on the ps structure.
    */
@@ -678,5 +683,5 @@
 
 /******************************************************************************
- * If !strict, the list may contain NULLs and VK records may point to NULL data.
+ * If !strict, the list may contain NULLs, VK records may point to NULL.
  ******************************************************************************/
 REGF_VK_REC** regfi_load_valuelist(REGF_FILE* file, uint32 offset, 
@@ -686,14 +691,17 @@
   REGF_VK_REC** ret_val;
   REGF_HBIN* hbin;
-  uint32 i, vk_offset, vk_max_length;
+  uint32 i, vk_offset, vk_max_length, usable_num_values;
   uint32* voffsets;
 
   if((num_values+1) * sizeof(uint32) > max_size)
-    return NULL;
-
-  /* TODO: For now, everything strict seems to make sense on this call.
-   *       Maybe remove the parameter or use it for other things.
-   */
-  voffsets = regfi_parse_valuelist(file, offset, num_values, true);
+  {
+    if(strict)
+      return NULL;
+    usable_num_values = max_size/sizeof(uint32) - sizeof(uint32);
+  }
+  else
+    usable_num_values = num_values;
+
+  voffsets = regfi_parse_valuelist(file, offset, usable_num_values, strict);
   if(voffsets == NULL)
     return NULL;
@@ -706,5 +714,5 @@
   }
   
-  for(i=0; i < num_values; i++)
+  for(i=0; i < usable_num_values; i++)
   {
     hbin = regfi_lookup_hbin(file, voffsets[i]);
@@ -739,6 +747,6 @@
 
 /*******************************************************************
- * TODO: Need to add full key caching using a 
- *       custom cache structure.
+ * XXX: Need to add full key caching using a 
+ *      custom cache structure.
  *******************************************************************/
 REGF_NK_REC* regfi_load_key(REGF_FILE* file, uint32 offset, bool strict)
@@ -800,6 +808,5 @@
       if(strict)
       {
-	free(nk);
-	/* TODO: need convenient way to free nk->values deeply in all cases. */
+	regfi_key_free(nk);
 	return NULL;
       }
@@ -815,5 +822,5 @@
       if(nk->subkeys == NULL)
       {
-	/* TODO: temporary hack to get around 'ri' records */
+	/* XXX: Temporary hack to get around 'ri' records */
 	nk->num_subkeys = 0;
       }
@@ -1031,6 +1038,11 @@
   }
 
-  /* TODO: come up with a better secret. */
-  ret_val->sk_recs = lru_cache_create(127, 0xDEADBEEF, true);
+  /* This secret isn't very secret, but we don't need a good one.  This 
+   * secret is just designed to prevent someone from trying to blow our
+   * caching and make things slow.
+   */
+  ret_val->sk_recs = lru_cache_create(127, 0x15DEAD05^time(NULL)
+				           ^(getpid()<<16)^(getppid()<<8),
+				      true);
 
   ret_val->f = fh;
@@ -1367,5 +1379,5 @@
 
 /*******************************************************************
- * TODO: add way to return more detailed error information.
+ * XXX: Add way to return more detailed error information.
  *******************************************************************/
 REGF_FILE* regfi_parse_regf(int fd, bool strict)
@@ -1441,6 +1453,5 @@
  * along with it's associated cells.
  *******************************************************************/
-/* TODO: Need a way to return types of errors.  Also need to free 
- *       the hbin/ps when an error occurs.
+/* XXX: Need a way to return types of errors.
  */
 REGF_HBIN* regfi_parse_hbin(REGF_FILE* file, uint32 offset, bool strict)
@@ -1485,6 +1496,7 @@
    * the end of the file. 
    */
-  /* TODO: This may need to be relaxed for dealing with 
-   *       partial or corrupt files. */
+  /* XXX: This may need to be relaxed for dealing with 
+   *      partial or corrupt files. 
+   */
   if((offset + hbin->block_size > file->file_length)
      || (hbin->block_size & 0xFFFFF000) != hbin->block_size)
@@ -1515,5 +1527,7 @@
   if((nk_header[0x0] != 'n') || (nk_header[0x1] != 'k'))
   {
-    /* TODO: deal with subkey-lists that reference other subkey-lists. */
+    /* XXX: Deal with subkey-lists that reference other subkey-lists
+     *      (e.g. 'ri' records). 
+     */
     return NULL;
   }
@@ -1549,5 +1563,15 @@
   ret_val->mtime.low = IVAL(nk_header, 0x4);
   ret_val->mtime.high = IVAL(nk_header, 0x8);
-  
+  /* If the key is unallocated and the MTIME is earlier than Jan 1, 1990
+   * or later than Jan 1, 2290, we consider this a bad key.  This helps
+   * weed out some false positives during deleted data recovery.
+   */
+  if(unalloc
+     && ((ret_val->mtime.high < REGFI_MTIME_MIN_HIGH 
+	  && ret_val->mtime.low < REGFI_MTIME_MIN_LOW)
+	 || (ret_val->mtime.high > REGFI_MTIME_MAX_HIGH 
+	     && ret_val->mtime.low > REGFI_MTIME_MAX_LOW)))
+    return NULL;
+
   ret_val->unknown1 = IVAL(nk_header, 0xC);
   ret_val->parent_off = IVAL(nk_header, 0x10);
@@ -1559,5 +1583,5 @@
   ret_val->values_off = IVAL(nk_header, 0x28);
   ret_val->sk_off = IVAL(nk_header, 0x2C);
-  /* TODO: currently we do nothing with class names.  Need to investigate. */
+  /* XXX: currently we do nothing with class names.  Need to investigate. */
   ret_val->classname_off = IVAL(nk_header, 0x30);
 
@@ -1758,7 +1782,7 @@
     if(cell_length - 4 < length)
     {
-      /* TODO: This strict condition has been triggered in multiple registries.
-       *       Not sure the cause, but the data length values are very large,
-       *       such as 53392.
+      /* XXX: This strict condition has been triggered in multiple registries.
+       *      Not sure the cause, but the data length values are very large,
+       *      such as 53392.
        */
       if(strict)
@@ -1768,6 +1792,6 @@
     }
 
-    /* TODO: There is currently no check to ensure the data 
-     *       cell doesn't cross HBIN boundary.
+    /* XXX: There is currently no check to ensure the data 
+     *      cell doesn't cross HBIN boundary.
      */
 
@@ -1816,5 +1840,5 @@
       
       if((cell_len == 0) || ((cell_len & 0xFFFFFFF8) != cell_len))
-	/* TODO: should report an error here. */
+	/* XXX: should report an error here. */
 	break;
       
