Changeset 157


Ignore:
Timestamp:
11/22/09 19:47:22 (14 years ago)
Author:
tim
Message:

reorganized data parsing in regfi

simplified some length validation

added big data support to reglookup-recover

fixed reglookup-recover's handling of data values in the offset

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r51 r157  
    44################################################################################
    55
    6 SVN_URL=svn+ssh://sentinelchicken.org/home/projects/subversion/reglookup
     6SVN_URL=svn+ssh://pascal.sentinelchicken.org/home/projects/subversion/reglookup
    77SUB_DIRS=$(wildcard releases/*) trunk
    88
     
    1212
    1313
    14 RELEASE_NAME=reglookup-test
     14RELEASE_NAME=reglookup-trunk
    1515RELEASE_DEST=.
    1616
  • trunk/doc/devel/TODO

    r153 r157  
    1515   descriptor information.  Maybe by MTIME as well.
    1616
    17  - Testing, testing, and more testing.  reglookup needs to be tested on
    18    NT/XP/2k3/Vista.  A regression test suite would be nice too.  Some
    19    thoughts on this include a script which randomly fuzzes an existing
    20    registry file, and tries to detect crashes of reglookup when parsing
    21    it.  Another test script might randomly truncate an existing registry
    22    file, which will help improve reglookup's parsing on fragmentary
    23    files.
     17 - Testing, testing, and more testing.  reglookup needs to be more
     18   heavily tested on all recent Windows platforms.  A regression test
     19   suite would be nice too.  Some thoughts on this include a script
     20   which randomly fuzzes an existing registry file, and tries to detect
     21   crashes of reglookup when parsing it.  Another test script might
     22   randomly truncate an existing registry file, which will help improve
     23   reglookup's parsing on fragmentary files.
    2424
    2525 - Build system.  I do not wish to use automake/autoconf in this
     
    5050   to integrate parts that are being kept into regfi or other modules.
    5151
    52  - Need to figure out a reasonably correct way to convert UTF-16LE charaters
    53    to ASCII under Windows/MingW or other platforms that don't have proper
    54    libiconv support yet.  Then a build-time option or autodetection can
    55    dictate which version of conversion function is used.
     52 - Consider switching from libiconv to Joachim Metz's libuna for
     53   increased portability and easier builds.
    5654
    5755 - Grep through the source for 'XXX', and you'll find more.
  • trunk/include/regfi.h

    r152 r157  
    105105#define REGFI_SK_MIN_LENGTH        0x14
    106106#define REGFI_SUBKEY_LIST_MIN_LEN  0x4
     107#define REGFI_BIG_DATA_MIN_LENGTH  0xC
    107108
    108109
     
    444445
    445446
     447
     448
    446449/******************************************************************************/
    447450/*                         Main iterator API                                  */
     
    468471bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
    469472
    470 bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i,
    471                                                  const char* subkey_name);
    472473bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i,
    473474                                               const char** path);
     
    478479REGFI_NK_REC*         regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
    479480REGFI_NK_REC*         regfi_iterator_next_subkey(REGFI_ITERATOR* i);
    480 
    481 bool                  regfi_iterator_find_value(REGFI_ITERATOR* i,
    482                                                 const char* value_name);
     481bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i,
     482                                                 const char* subkey_name);
     483
    483484REGFI_VK_REC*         regfi_iterator_first_value(REGFI_ITERATOR* i);
    484485REGFI_VK_REC*         regfi_iterator_cur_value(REGFI_ITERATOR* i);
    485486REGFI_VK_REC*         regfi_iterator_next_value(REGFI_ITERATOR* i);
     487bool                  regfi_iterator_find_value(REGFI_ITERATOR* i,
     488                                                const char* value_name);
     489
     490REGFI_DATA*           regfi_iterator_cur_data(REGFI_ITERATOR* i);
    486491
    487492
     
    500505                                           bool strict);
    501506
     507REGFI_BUFFER          regfi_load_data(REGFI_FILE* file, uint32 voffset,
     508                                      uint32 length, bool data_in_offset,
     509                                      bool strict);
     510
     511REGFI_BUFFER          regfi_load_big_data(REGFI_FILE* file, uint32 offset,
     512                                          uint32 data_length,uint32 cell_length,
     513                                          range_list* used_ranges,
     514                                          bool strict);
     515
    502516/* These are cached so return values don't need to be freed. */
    503517const REGFI_SK_REC*   regfi_load_sk(REGFI_FILE* file, uint32 offset,
    504518                                    bool strict);
    505 const REGFI_HBIN*     regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset);
    506 
     519const REGFI_HBIN*     regfi_lookup_hbin(REGFI_FILE* file, uint32 offset);
    507520
    508521
     
    535548                                     uint32 max_size, bool strict);
    536549
    537 REGFI_BUFFER          regfi_load_data(REGFI_FILE* file,
    538                                       uint32 data_type, uint32 offset,
    539                                       uint32 length, uint32 max_size,
    540                                       bool data_in_offset, bool strict);
    541 
    542 REGFI_BUFFER          regfi_load_big_data(REGFI_FILE* file,
    543                                           uint32 offset, uint32 data_length,
    544                                           uint32 cell_length, bool strict);
    545 
    546550REGFI_SK_REC*         regfi_parse_sk(REGFI_FILE* file, uint32 offset,
    547551                                     uint32 max_size, bool strict);
     
    556560                                            uint16* name_length,
    557561                                            uint32 max_size, bool strict);
     562
     563REGFI_BUFFER          regfi_parse_data(REGFI_FILE* file, uint32 offset,
     564                                       uint32 length, bool strict);
     565
     566REGFI_BUFFER          regfi_parse_little_data(REGFI_FILE* file, uint32 voffset,
     567                                              uint32 length, bool strict);
     568
    558569
    559570/* Dispose of previously parsed records */
     
    588599REGFI_NK_REC*         regfi_copy_nk(const REGFI_NK_REC* nk);
    589600REGFI_VK_REC*         regfi_copy_vk(const REGFI_VK_REC* vk);
     601int32                 regfi_calc_maxsize(REGFI_FILE* file, uint32 offset);
    590602
    591603#endif  /* _REGFI_H */
  • trunk/include/smb_deps.h

    r134 r157  
    4040#include "byteorder.h"
    4141
    42 #define DEBUG(lvl,body) 0
    43 
    44 void* zalloc(size_t size);
    45 void* zcalloc(size_t size, unsigned int count);
    46 
    4742/* From includes.h */
    4843
     44/* XXX: convert all code to use the more standard "*_t" types */
    4945#define uint8  uint8_t
    5046#define int16  int8_t
     
    5248#define int32  int32_t
    5349#define uint32 uint32_t
     50#define int64  int64_t
     51#define uint64 uint64_t
    5452
    5553#define MIN(a,b) ((a)<(b)?(a):(b))
    5654#define MAX(a,b) ((a)>(b)?(a):(b))
    57 
    58 extern int DEBUGLEVEL;
    5955
    6056/* End of stuff from includes.h */
  • trunk/lib/regfi.c

    r155 r157  
    471471
    472472
    473 /*******************************************************************
     473/******************************************************************************
    474474 * Given an offset and an hbin, is the offset within that hbin?
    475475 * The offset is a virtual file offset.
    476  *******************************************************************/
     476 ******************************************************************************/
    477477static bool regfi_offset_in_hbin(const REGFI_HBIN* hbin, uint32 voffset)
    478478{
     
    489489
    490490
    491 /*******************************************************************
    492  * Provide a virtual offset and receive the correpsonding HBIN
     491/******************************************************************************
     492 * Provide a physical offset and receive the correpsonding HBIN
    493493 * block for it.  NULL if one doesn't exist.
    494  *******************************************************************/
    495 const REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset)
    496 {
    497   return (const REGFI_HBIN*)range_list_find_data(file->hbins,
    498                                                  voffset+REGFI_REGF_SIZE);
    499 }
    500 
     494 ******************************************************************************/
     495const REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 offset)
     496{
     497  return (const REGFI_HBIN*)range_list_find_data(file->hbins, offset);
     498}
     499
     500
     501/******************************************************************************
     502 * Calculate the largest possible cell size given a physical offset.
     503 * Largest size is based on the HBIN the offset is currently a member of.
     504 * Returns negative values on error.
     505 * (Since cells can only be ~2^31 in size, this works out.)
     506 ******************************************************************************/
     507int32 regfi_calc_maxsize(REGFI_FILE* file, uint32 offset)
     508{
     509  const REGFI_HBIN* hbin = regfi_lookup_hbin(file, offset);
     510  if(hbin == NULL)
     511    return -1;
     512
     513  return (hbin->block_size + hbin->file_off) - offset;
     514}
    501515
    502516
     
    542556  REGFI_SUBKEY_LIST* ret_val;
    543557  REGFI_SUBKEY_LIST** sublists;
    544   const REGFI_HBIN* sublist_hbin;
    545   uint32 i, num_sublists, off, max_length;
     558  uint32 i, num_sublists, off;
     559  int32 sublist_maxsize;
    546560
    547561  if(depth_left == 0)
     
    565579    {
    566580      off = ret_val->elements[i].offset + REGFI_REGF_SIZE;
    567       sublist_hbin = regfi_lookup_hbin(file, ret_val->elements[i].offset);
    568       if(sublist_hbin == NULL)
     581
     582      sublist_maxsize = regfi_calc_maxsize(file, off);
     583      if(sublist_maxsize < 0)
    569584        sublists[i] = NULL;
    570585      else
    571       {
    572         max_length = sublist_hbin->block_size + sublist_hbin->file_off - off;
    573         sublists[i] = regfi_load_subkeylist_aux(file, off, max_length, strict,
    574                                                 depth_left-1);
    575       }
     586        sublists[i] = regfi_load_subkeylist_aux(file, off, sublist_maxsize,
     587                                                strict, depth_left-1);
    576588    }
    577589    talloc_free(ret_val);
     
    792804    ret_val->cell_size = max_size & 0xFFFFFFF8;
    793805  if((ret_val->cell_size < REGFI_SK_MIN_LENGTH)
    794      || (strict && ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8)))
     806     || (strict && (ret_val->cell_size & 0x00000007) != 0))
    795807  {
    796808    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size found while"
     
    808820  ret_val->desc_size = IVAL(sk_header, 0x10);
    809821
    810   if(ret_val->prev_sk_off != (ret_val->prev_sk_off & 0xFFFFFFF8)
    811      || ret_val->next_sk_off != (ret_val->next_sk_off & 0xFFFFFFF8))
     822  if((ret_val->prev_sk_off & 0x00000007) != 0
     823     || (ret_val->next_sk_off & 0x00000007) != 0)
    812824  {
    813825    regfi_add_message(file, REGFI_MSG_WARN, "SK record's next/previous offsets"
     
    873885  }
    874886
    875   if(cell_length != (cell_length & 0xFFFFFFF8))
     887  if((cell_length & 0x00000007) != 0)
    876888  {
    877889    regfi_add_message(file, REGFI_MSG_WARN, "Cell length not a multiple of 8"
     
    925937       *      with partial files. */
    926938      if((ret_val->elements[i] + REGFI_REGF_SIZE > file->file_length)
    927          || ((ret_val->elements[i] & 0xFFFFFFF8) != ret_val->elements[i]))
     939         || ((ret_val->elements[i] & 0x00000007) != 0))
    928940      {
    929941        regfi_add_message(file, REGFI_MSG_WARN, "Invalid value pointer"
     
    946958{
    947959  REGFI_VK_REC* ret_val = NULL;
    948   const REGFI_HBIN* hbin;
    949   uint32 data_offset, data_maxsize;
    950960  REGFI_BUFFER data;
    951 
    952   hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
    953   if(!hbin)
    954     return NULL;
    955  
    956   ret_val = regfi_parse_vk(file, offset,
    957                            hbin->block_size + hbin->file_off - offset, strict);
    958 
     961  int32 max_size;
     962
     963  max_size = regfi_calc_maxsize(file, offset);
     964  if(max_size < 0)
     965    return NULL;
     966 
     967  ret_val = regfi_parse_vk(file, offset, max_size, strict);
    959968  if(ret_val == NULL)
    960969    return NULL;
     
    964973  else
    965974  {
    966     if(ret_val->data_in_offset)
    967     {
    968       data = regfi_load_data(file, ret_val->type, ret_val->data_off,
    969                               ret_val->data_size, 4,
    970                               ret_val->data_in_offset, strict);
    971       ret_val->data = data.buf;
    972       ret_val->data_size = data.len;
    973     }
    974     else
    975     {
    976       hbin = regfi_lookup_hbin(file, ret_val->data_off);
    977       if(hbin)
    978       {
    979         data_offset = ret_val->data_off+REGFI_REGF_SIZE;
    980         data_maxsize = hbin->block_size + hbin->file_off - data_offset;
    981         data = regfi_load_data(file, ret_val->type, data_offset,
    982                                 ret_val->data_size, data_maxsize,
    983                                 ret_val->data_in_offset, strict);
    984         ret_val->data = data.buf;
    985         ret_val->data_size = data.len;
    986 
    987       }
    988       else
    989       {
    990         regfi_add_message(file, REGFI_MSG_WARN, "Could not find HBIN for data"
    991                           " while parsing VK record at offset 0x%.8X.",
    992                           ret_val->offset);
    993         ret_val->data = NULL;
    994       }
    995     }
     975    data = regfi_load_data(file, ret_val->data_off, ret_val->data_size,
     976                           ret_val->data_in_offset, strict);
     977    ret_val->data = data.buf;
     978    ret_val->data_size = data.len;
    996979
    997980    if(ret_val->data == NULL)
     
    10411024REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset, bool strict)
    10421025{
    1043   const REGFI_HBIN* hbin;
    1044   const REGFI_HBIN* sub_hbin;
    10451026  REGFI_NK_REC* nk;
    1046   uint32 max_length, off;
    1047 
    1048   hbin = regfi_lookup_hbin(file, offset-REGFI_REGF_SIZE);
    1049   if (hbin == NULL)
     1027  uint32 off;
     1028  int32 max_size;
     1029
     1030  max_size = regfi_calc_maxsize(file, offset);
     1031  if (max_size < 0)
    10501032    return NULL;
    10511033
    10521034  /* get the initial nk record */
    1053   max_length = hbin->block_size + hbin->file_off - offset;
    1054   if((nk = regfi_parse_nk(file, offset, max_length, true)) == NULL)
     1035  if((nk = regfi_parse_nk(file, offset, max_size, true)) == NULL)
    10551036  {
    10561037    regfi_add_message(file, REGFI_MSG_ERROR, "Could not load NK record at"
     
    10621043  if(nk->num_values && (nk->values_off!=REGFI_OFFSET_NONE))
    10631044  {
    1064     sub_hbin = hbin;
    1065     if(!regfi_offset_in_hbin(hbin, nk->values_off))
    1066       sub_hbin = regfi_lookup_hbin(file, nk->values_off);
    1067    
    1068     if(sub_hbin == NULL)
     1045    off = nk->values_off + REGFI_REGF_SIZE;
     1046    max_size = regfi_calc_maxsize(file, off);
     1047    if(max_size < 0)
    10691048    {
    10701049      if(strict)
     
    10791058    else
    10801059    {
    1081       off = nk->values_off + REGFI_REGF_SIZE;
    1082       max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    1083       nk->values = regfi_load_valuelist(file, off, nk->num_values, max_length,
    1084                                         true);
     1060      nk->values = regfi_load_valuelist(file, off, nk->num_values,
     1061                                        max_size, true);
    10851062      if(nk->values == NULL)
    10861063      {
     
    11001077  if(nk->num_subkeys && (nk->subkeys_off != REGFI_OFFSET_NONE))
    11011078  {
    1102     sub_hbin = hbin;
    1103     if(!regfi_offset_in_hbin(hbin, nk->subkeys_off))
    1104       sub_hbin = regfi_lookup_hbin(file, nk->subkeys_off);
    1105 
    1106     if(sub_hbin == NULL)
     1079    off = nk->subkeys_off + REGFI_REGF_SIZE;
     1080    max_size = regfi_calc_maxsize(file, off);
     1081    if(max_size < 0)
    11071082    {
    11081083      if(strict)
     
    11161091    else
    11171092    {
    1118       off = nk->subkeys_off + REGFI_REGF_SIZE;
    1119       max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    11201093      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys,
    1121                                           max_length, true);
     1094                                          max_size, true);
    11221095
    11231096      if(nk->subkeys == NULL)
     
    11401113{
    11411114  REGFI_SK_REC* ret_val = NULL;
    1142   const REGFI_HBIN* hbin;
    1143   uint32 max_length;
     1115  int32 max_size;
    11441116  void* failure_ptr = NULL;
    11451117 
     
    11531125  if(ret_val == NULL)
    11541126  {
    1155     hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
    1156     if(hbin == NULL)
     1127    max_size = regfi_calc_maxsize(file, offset);
     1128    if(max_size < 0)
    11571129      return NULL;
    11581130
    1159     max_length = hbin->block_size + hbin->file_off - offset;
    1160     ret_val = regfi_parse_sk(file, offset, max_length, strict);
     1131    ret_val = regfi_parse_sk(file, offset, max_size, strict);
    11611132    if(ret_val == NULL)
    11621133    { /* Cache the parse failure and bail out. */
     
    18681839{
    18691840  uint8 nk_header[REGFI_NK_MIN_LENGTH];
    1870   const REGFI_HBIN *hbin;
    18711841  REGFI_NK_REC* ret_val;
    18721842  uint32 length,cell_length;
    1873   uint32 class_offset, class_maxsize;
     1843  uint32 class_offset;
     1844  int32 class_maxsize;
    18741845  bool unalloc = false;
    18751846
     
    19061877    ret_val->cell_size = max_size & 0xFFFFFFF8;
    19071878  if((ret_val->cell_size < REGFI_NK_MIN_LENGTH)
    1908      || (strict && ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8)))
     1879     || (strict && (ret_val->cell_size & 0x00000007) != 0))
    19091880  {
    19101881    regfi_add_message(file, REGFI_MSG_WARN, "A length check failed while"
     
    20041975  if(ret_val->classname_off != REGFI_OFFSET_NONE)
    20051976  {
    2006     hbin = regfi_lookup_hbin(file, ret_val->classname_off);
    2007     if(hbin)
    2008     {
    2009       class_offset = ret_val->classname_off+REGFI_REGF_SIZE;
    2010       class_maxsize = hbin->block_size + hbin->file_off - class_offset;
     1977    class_offset = ret_val->classname_off + REGFI_REGF_SIZE;
     1978    class_maxsize = regfi_calc_maxsize(file, class_offset);
     1979    if(class_maxsize > 0)
     1980    {
    20111981      ret_val->classname
    20121982        = regfi_parse_classname(file, class_offset, &ret_val->classname_length,
     
    20442014
    20452015  if(*name_length > 0 && offset != REGFI_OFFSET_NONE
    2046      && offset == (offset & 0xFFFFFFF8))
     2016     && (offset & 0x00000007) == 0)
    20472017  {
    20482018    if(!regfi_parse_cell(file->fd, offset, NULL, 0, &cell_length, &unalloc))
     
    20532023    }
    20542024
    2055     if((cell_length & 0xFFFFFFF8) != cell_length)
     2025    if((cell_length & 0x0000007) != 0)
    20562026    {
    20572027      regfi_add_message(file, REGFI_MSG_ERROR, "Cell length not a multiple of 8"
     
    21292099    ret_val->cell_size = max_size & 0xFFFFFFF8;
    21302100  if((ret_val->cell_size < REGFI_VK_MIN_LENGTH)
    2131      || ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8))
     2101     || (ret_val->cell_size & 0x00000007) != 0)
    21322102  {
    21332103    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size encountered"
     
    21542124  raw_data_size = IVAL(vk_header, 0x4);
    21552125  ret_val->data_size = raw_data_size & ~REGFI_VK_DATA_IN_OFFSET;
     2126  /* The data is typically stored in the offset if the size <= 4,
     2127   * in which case this flag is set.
     2128   */
    21562129  ret_val->data_in_offset = (bool)(raw_data_size & REGFI_VK_DATA_IN_OFFSET);
    21572130  ret_val->data_off = IVAL(vk_header, 0x8);
     
    22152188
    22162189/******************************************************************************
    2217 *******************************************************************************/
    2218 REGFI_BUFFER regfi_load_data(REGFI_FILE* file,
    2219                              uint32 data_type, uint32 offset,
    2220                              uint32 length, uint32 max_size,
    2221                              bool data_in_offset, bool strict)
     2190 *
     2191 ******************************************************************************/
     2192REGFI_BUFFER regfi_load_data(REGFI_FILE* file, uint32 voffset,
     2193                             uint32 length, bool data_in_offset,
     2194                             bool strict)
    22222195{
    22232196  REGFI_BUFFER ret_val;
    2224   uint32 read_length, cell_length;
    2225   uint8 i;
     2197  uint32 cell_length, offset;
     2198  int32 max_size;
    22262199  bool unalloc;
    22272200 
    2228   /* The data is typically stored in the offset if the size <= 4 */
    22292201  if(data_in_offset)
    2230   {
    2231     if(length > 4)
    2232     {
    2233       regfi_add_message(file, REGFI_MSG_ERROR, "Data in offset but length > 4"
    2234                         " while parsing data record at offset 0x%.8X.",
    2235                         offset);
     2202    return regfi_parse_little_data(file, voffset, length, strict);
     2203  else
     2204  {
     2205    offset = voffset + REGFI_REGF_SIZE;
     2206    max_size = regfi_calc_maxsize(file, offset);
     2207    if(max_size < 0)
     2208    {
     2209      regfi_add_message(file, REGFI_MSG_WARN, "Could not find HBIN for data"
     2210                        " at offset 0x%.8X.", offset);
    22362211      goto fail;
    22372212    }
    2238 
    2239     if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
    2240       goto fail;
    2241     ret_val.len = length;
    2242 
    2243     for(i = 0; i < length; i++)
    2244       ret_val.buf[i] = (uint8)((offset >> i*8) & 0xFF);
    2245   }
    2246   else
    2247   {
     2213   
    22482214    if(!regfi_parse_cell(file->fd, offset, NULL, 0,
    22492215                         &cell_length, &unalloc))
     
    22542220    }
    22552221
    2256     if((cell_length & 0xFFFFFFF8) != cell_length)
     2222    if((cell_length & 0x00000007) != 0)
    22572223    {
    22582224      regfi_add_message(file, REGFI_MSG_WARN, "Cell length not multiple of 8"
     
    22672233                        " while parsing data record at offset 0x%.8X.",
    22682234                        offset);
    2269       if(strict)
    2270         goto fail;
    2271       else
    2272         cell_length = max_size;
     2235      goto fail;
    22732236    }
    22742237
     
    22822245      {
    22832246        /* Attempt to parse a big data record */
    2284         return regfi_load_big_data(file, offset, length, cell_length, strict);
     2247        return regfi_load_big_data(file, offset, length, cell_length,
     2248                                   NULL, strict);
    22852249      }
    22862250      else
     
    22972261    }
    22982262
    2299     if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
    2300       goto fail;
    2301     ret_val.len = length;
    2302 
    2303     read_length = length;
    2304     if((regfi_read(file->fd, ret_val.buf, &read_length) != 0)
    2305        || read_length != length)
    2306     {
    2307       regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
    2308                         " parsing data record at offset 0x%.8X.", offset);
    2309       talloc_free(ret_val.buf);
    2310       goto fail;
    2311     }
     2263    ret_val = regfi_parse_data(file, offset, length, strict);
    23122264  }
    23132265
     
    23222274
    23232275/******************************************************************************
     2276 * Parses the common case data records stored in a single cell.
     2277 ******************************************************************************/
     2278REGFI_BUFFER regfi_parse_data(REGFI_FILE* file, uint32 offset,
     2279                              uint32 length, bool strict)
     2280{
     2281  REGFI_BUFFER ret_val;
     2282  uint32 read_length;
     2283
     2284  ret_val.buf = NULL;
     2285  ret_val.len = 0;
     2286 
     2287  if(lseek(file->fd, offset+4, SEEK_SET) == -1)
     2288  {
     2289    regfi_add_message(file, REGFI_MSG_WARN, "Could not seek while "
     2290                      "reading data at offset 0x%.8X.", offset);
     2291    return ret_val;
     2292  }
     2293
     2294  if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2295    return ret_val;
     2296  ret_val.len = length;
     2297 
     2298  read_length = length;
     2299  if((regfi_read(file->fd, ret_val.buf, &read_length) != 0)
     2300     || read_length != length)
     2301  {
     2302    regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
     2303                      " parsing data record at offset 0x%.8X.", offset);
     2304    talloc_free(ret_val.buf);
     2305    ret_val.buf = NULL;
     2306    ret_val.buf = 0;
     2307  }
     2308
     2309  return ret_val;
     2310}
     2311
     2312
     2313
     2314/******************************************************************************
     2315 *
     2316 ******************************************************************************/
     2317REGFI_BUFFER regfi_parse_little_data(REGFI_FILE* file, uint32 voffset,
     2318                                     uint32 length, bool strict)
     2319{
     2320  REGFI_BUFFER ret_val;
     2321  uint8 i;
     2322
     2323  ret_val.buf = NULL;
     2324  ret_val.len = 0;
     2325
     2326  if(length > 4)
     2327  {
     2328    regfi_add_message(file, REGFI_MSG_ERROR, "Data in offset but length > 4"
     2329                      " while parsing data record. (voffset=0x%.8X, length=%d)",
     2330                      voffset, length);
     2331    return ret_val;
     2332  }
     2333
     2334  if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2335    return ret_val;
     2336  ret_val.len = length;
     2337 
     2338  for(i = 0; i < length; i++)
     2339    ret_val.buf[i] = (uint8)((voffset >> i*8) & 0xFF);
     2340
     2341  return ret_val;
     2342}
     2343
     2344/******************************************************************************
     2345*******************************************************************************/
     2346REGFI_BUFFER regfi_parse_big_data_header(REGFI_FILE* file, uint32 offset,
     2347                                         uint32 max_size, bool strict)
     2348{
     2349  REGFI_BUFFER ret_val;
     2350  uint32 cell_length;
     2351  bool unalloc;
     2352
     2353  /* XXX: do something with unalloc? */
     2354  ret_val.buf = (uint8*)talloc_array(NULL, uint8, REGFI_BIG_DATA_MIN_LENGTH);
     2355  if(ret_val.buf == NULL)
     2356    goto fail;
     2357
     2358  if(REGFI_BIG_DATA_MIN_LENGTH > max_size)
     2359  {
     2360    regfi_add_message(file, REGFI_MSG_WARN, "Big data header exceeded max_size "
     2361                      "while parsing big data header at offset 0x%.8X.",offset);
     2362    goto fail;
     2363  }
     2364
     2365  if(!regfi_parse_cell(file->fd, offset, ret_val.buf, REGFI_BIG_DATA_MIN_LENGTH,
     2366                       &cell_length, &unalloc))
     2367  {
     2368    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2369                      " parsing big data header at offset 0x%.8X.", offset);
     2370    goto fail;
     2371  }
     2372
     2373  if((ret_val.buf[0] != 'd') || (ret_val.buf[1] != 'b'))
     2374  {
     2375    regfi_add_message(file, REGFI_MSG_WARN, "Unknown magic number"
     2376                      " (0x%.2X, 0x%.2X) encountered while parsing"
     2377                      " big data header at offset 0x%.8X.",
     2378                      ret_val.buf[0], ret_val.buf[1], offset);
     2379    goto fail;
     2380  }
     2381
     2382  ret_val.len = REGFI_BIG_DATA_MIN_LENGTH;
     2383  return ret_val;
     2384
     2385 fail:
     2386  if(ret_val.buf != NULL)
     2387  {
     2388    talloc_free(ret_val.buf);
     2389    ret_val.buf = NULL;
     2390  }
     2391  ret_val.len = 0;
     2392  return ret_val;
     2393}
     2394
     2395
     2396
     2397/******************************************************************************
     2398 *
     2399 ******************************************************************************/
     2400uint32* regfi_parse_big_data_indirect(REGFI_FILE* file, uint32 offset,
     2401                                      uint16 num_chunks, bool strict)
     2402{
     2403  uint32* ret_val;
     2404  uint32 indirect_length;
     2405  int32 max_size;
     2406  uint16 i;
     2407  bool unalloc;
     2408
     2409  /* XXX: do something with unalloc? */
     2410
     2411  max_size = regfi_calc_maxsize(file, offset);
     2412  if((max_size < 0) || (num_chunks*sizeof(uint32) + 4 > max_size))
     2413    return NULL;
     2414
     2415  ret_val = (uint32*)talloc_array(NULL, uint32, num_chunks);
     2416  if(ret_val == NULL)
     2417    goto fail;
     2418
     2419  if(!regfi_parse_cell(file->fd, offset, (uint8*)ret_val,
     2420                       num_chunks*sizeof(uint32),
     2421                       &indirect_length, &unalloc))
     2422  {
     2423    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2424                      " parsing big data indirect record at offset 0x%.8X.",
     2425                      offset);
     2426    goto fail;
     2427  }
     2428
     2429  /* Convert pointers to proper endianess, verify they are aligned. */
     2430  for(i=0; i<num_chunks; i++)
     2431  {
     2432    ret_val[i] = IVAL(ret_val, i*sizeof(uint32));
     2433    if((ret_val[i] & 0x00000007) != 0)
     2434      goto fail;
     2435  }
     2436 
     2437  return ret_val;
     2438
     2439 fail:
     2440  if(ret_val != NULL)
     2441    talloc_free(ret_val);
     2442  return NULL;
     2443}
     2444
     2445
     2446/******************************************************************************
     2447 * Arguments:
     2448 *  file       --
     2449 *  offsets    -- list of virtual offsets.
     2450 *  num_chunks --
     2451 *  strict     --
     2452 *
     2453 * Returns:
     2454 *  A range_list with physical offsets and complete lengths
     2455 *  (including cell headers) of associated cells. 
     2456 *  No data in range_list elements.
     2457 ******************************************************************************/
     2458range_list* regfi_parse_big_data_cells(REGFI_FILE* file, uint32* offsets,
     2459                                       uint16 num_chunks, bool strict)
     2460{
     2461  uint32 cell_length, chunk_offset, data_left;
     2462  range_list* ret_val;
     2463  uint16 i;
     2464  bool unalloc;
     2465 
     2466  /* XXX: do something with unalloc? */
     2467  ret_val = range_list_new();
     2468  if(ret_val == NULL)
     2469    goto fail;
     2470 
     2471  for(i=0; (i<num_chunks) && (data_left>0); i++)
     2472  {
     2473    chunk_offset = offsets[i]+REGFI_REGF_SIZE;
     2474    if(!regfi_parse_cell(file->fd, chunk_offset, NULL, 0,
     2475                         &cell_length, &unalloc))
     2476    {
     2477      regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2478                        " parsing big data chunk at offset 0x%.8X.",
     2479                        chunk_offset);
     2480      goto fail;
     2481    }
     2482
     2483    if(!range_list_add(ret_val, chunk_offset, cell_length, NULL))
     2484      goto fail;
     2485  }
     2486
     2487  return ret_val;
     2488
     2489 fail:
     2490  if(ret_val != NULL)
     2491    range_list_free(ret_val);
     2492  return NULL;
     2493}
     2494
     2495
     2496/******************************************************************************
    23242497*******************************************************************************/
    23252498REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file,
    23262499                                 uint32 offset, uint32 data_length,
    2327                                  uint32 cell_length, bool strict)
     2500                                 uint32 cell_length, range_list* used_ranges,
     2501                                 bool strict)
    23282502{
    23292503  REGFI_BUFFER ret_val;
    23302504  uint16 num_chunks, i;
    2331   uint32 indirect_offset, indirect_length, chunk_length, chunk_offset;
    2332   uint32 read_length, data_left;
    2333   bool unalloc;
    2334   uint32* indirect_ptrs;
    2335   uint8* big_data_cell = (uint8*)malloc(cell_length*sizeof(uint8));
    2336   if(big_data_cell == NULL)
     2505  uint32 read_length, data_left, tmp_len, indirect_offset;
     2506  uint32* indirect_ptrs = NULL;
     2507  REGFI_BUFFER bd_header;
     2508  range_list* bd_cells = NULL;
     2509  const range_list_element* cell_info;
     2510
     2511  ret_val.buf = NULL;
     2512
     2513  /* XXX: Add better error/warning messages */
     2514
     2515  bd_header = regfi_parse_big_data_header(file, offset, cell_length, strict);
     2516  if(bd_header.buf == NULL)
    23372517    goto fail;
    23382518
    2339   if(!regfi_parse_cell(file->fd, offset, big_data_cell, cell_length-4,
    2340                        &cell_length, &unalloc))
    2341   {
    2342     regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2343                       " parsing big data record at offset 0x%.8X.", offset);
    2344     free(big_data_cell);
    2345     goto fail;
    2346   }
    2347  
    2348   if((big_data_cell[0] != 'd') || (big_data_cell[1] != 'b'))
    2349   {
    2350     regfi_add_message(file, REGFI_MSG_WARN, "Unknown magic number"
    2351                       " (0x%.2X, 0x%.2X) encountered while parsing"
    2352                       " big data record at offset 0x%.8X.",
    2353                       big_data_cell[0], big_data_cell[1], offset);
    2354     free(big_data_cell);
    2355     goto fail;
    2356   }
    2357   num_chunks = SVAL(big_data_cell, 0x2);
    2358   /* XXX: Should check sanity of pointers here and in the indirect
    2359    *      block.  At least ensure they are a multiple of 8.
    2360    */
    2361   indirect_offset = IVAL(big_data_cell, 0x4) + REGFI_REGF_SIZE;
    2362   free(big_data_cell);
    2363 
    2364   indirect_ptrs = (uint32*)malloc(num_chunks*sizeof(uint32));
     2519  /* Keep track of used space for use by reglookup-recover */
     2520  if(used_ranges != NULL)
     2521    if(!range_list_add(used_ranges, offset, cell_length, NULL))
     2522      goto fail;
     2523
     2524  num_chunks = SVAL(bd_header.buf, 0x2);
     2525  indirect_offset = IVAL(bd_header.buf, 0x4) + REGFI_REGF_SIZE;
     2526  talloc_free(bd_header.buf);
     2527
     2528  indirect_ptrs = regfi_parse_big_data_indirect(file, indirect_offset,
     2529                                                num_chunks, strict);
    23652530  if(indirect_ptrs == NULL)
    23662531    goto fail;
    23672532
    2368   if(!regfi_parse_cell(file->fd, indirect_offset, (uint8*)indirect_ptrs,
    2369                        num_chunks*sizeof(uint32),
    2370                        &indirect_length, &unalloc))
    2371   {
    2372     regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2373                       " parsing big data indirect record at offset 0x%.8X.",
    2374                       offset);
    2375     free(indirect_ptrs);
     2533  if(used_ranges != NULL)
     2534    if(!range_list_add(used_ranges, indirect_offset, num_chunks*4+4, NULL))
     2535      goto fail;
     2536 
     2537  if((ret_val.buf = talloc_array(NULL, uint8_t, data_length)) == NULL)
    23762538    goto fail;
    2377   }
    2378  
    2379   if((ret_val.buf = talloc_array(NULL, uint8_t, data_length)) == NULL)
    2380   {
    2381     free(indirect_ptrs);
     2539  data_left = data_length;
     2540
     2541  bd_cells = regfi_parse_big_data_cells(file, indirect_ptrs, num_chunks, strict);
     2542  if(bd_cells == NULL)
    23822543    goto fail;
    2383   }
    2384   data_left = data_length;
    2385 
     2544
     2545  talloc_free(indirect_ptrs);
     2546  indirect_ptrs = NULL;
     2547 
    23862548  for(i=0; (i<num_chunks) && (data_left>0); i++)
    23872549  {
    2388     /* Fix endianness of pointer and convert to physical offset */
    2389     chunk_offset = IVAL(indirect_ptrs, i*4) + REGFI_REGF_SIZE;
    2390     if(!regfi_parse_cell(file->fd, chunk_offset, NULL, 0,
    2391                          &chunk_length, &unalloc))
    2392     {
    2393       regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2394                         " parsing big data chunk at offset 0x%.8X.",
    2395                         chunk_offset);
    2396       if(strict)
    2397         goto chunk_fail;
    2398       else
    2399         break;
    2400     }
    2401 
    2402     /* XXX: This should be "chunk_length-4" to account for the 4 byte cell
     2550    cell_info = range_list_get(bd_cells, i);
     2551    if(cell_info == NULL)
     2552      goto fail;
     2553
     2554    /* XXX: This should be "cell_info->length-4" to account for the 4 byte cell
    24032555     *      length.  However, it has been observed that some (all?) chunks
    24042556     *      have an additional 4 bytes of 0 at the end of their cells that
    24052557     *      isn't part of the data, so we're trimming that off too.
     2558     *      Perhaps it's just an 8 byte alignment requirement...
    24062559     */
    2407     if(chunk_length-8 >= data_left)
     2560    if(cell_info->length - 8 >= data_left)
     2561    {
     2562      if(i+1 != num_chunks)
     2563      {
     2564        regfi_add_message(file, REGFI_MSG_WARN, "Left over chunks detected "
     2565                          "while constructing big data at offset 0x%.8X "
     2566                          "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2567      }
    24082568      read_length = data_left;
     2569    }
    24092570    else
    2410       read_length = chunk_length-8;
    2411 
     2571      read_length = cell_info->length - 8;
     2572
     2573
     2574    if(read_length > regfi_calc_maxsize(file, cell_info->offset))
     2575    {
     2576      regfi_add_message(file, REGFI_MSG_WARN, "A chunk exceeded the maxsize "
     2577                        "while constructing big data at offset 0x%.8X "
     2578                        "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2579      goto fail;
     2580    }
     2581
     2582    if(lseek(file->fd, cell_info->offset+sizeof(uint32), SEEK_SET) == -1)
     2583    {
     2584      regfi_add_message(file, REGFI_MSG_WARN, "Could not seek to chunk while "
     2585                        "constructing big data at offset 0x%.8X "
     2586                        "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2587      goto fail;
     2588    }
     2589
     2590    tmp_len = read_length;
    24122591    if(regfi_read(file->fd, ret_val.buf+(data_length-data_left),
    2413                   &read_length) != 0)
     2592                  &read_length) != 0 || (read_length != tmp_len))
    24142593    {
    24152594      regfi_add_message(file, REGFI_MSG_WARN, "Could not read data chunk while"
    2416                         " constructing big data at offset 0x%.8X.",
    2417                         chunk_offset);
    2418       if(strict)
    2419         goto chunk_fail;
    2420       else
    2421         break;
    2422     }
     2595                        " constructing big data at offset 0x%.8X"
     2596                        " (chunk offset 0x%.8X).", offset, cell_info->offset);
     2597      goto fail;
     2598    }
     2599
     2600    if(used_ranges != NULL)
     2601      if(!range_list_add(used_ranges, cell_info->offset,cell_info->length,NULL))
     2602        goto fail;
    24232603
    24242604    data_left -= read_length;
    24252605  }
    2426   free(indirect_ptrs);
     2606  range_list_free(bd_cells);
     2607
    24272608  ret_val.len = data_length-data_left;
    2428 
    2429   return ret_val;
    2430 
    2431  chunk_fail:
    2432   free(indirect_ptrs);
    2433   talloc_free(ret_val.buf);
     2609  return ret_val;
     2610
    24342611 fail:
     2612  if(ret_val.buf != NULL)
     2613    talloc_free(ret_val.buf);
     2614  if(indirect_ptrs != NULL)
     2615    talloc_free(indirect_ptrs);
     2616  if(bd_cells != NULL)
     2617    range_list_free(bd_cells);
    24352618  ret_val.buf = NULL;
    24362619  ret_val.len = 0;
     
    24662649        break;
    24672650     
    2468       if((cell_len == 0) || ((cell_len & 0xFFFFFFF8) != cell_len))
     2651      if((cell_len == 0) || ((cell_len & 0x00000007) != 0))
    24692652      {
    24702653        regfi_add_message(file, REGFI_MSG_ERROR, "Bad cell length encountered"
  • trunk/lib/smb_deps.c

    r147 r157  
    2626#include "smb_deps.h"
    2727
    28 
    29 /* These act as replacements for numerous Samba memory allocation
    30  *   functions.
    31  */
    32 void* zalloc(size_t size)
    33 {
    34   void* ret_val = NULL;
    35   if((size > 0) && (ret_val = (void*)malloc(size)) != NULL)
    36     memset(ret_val, 0, size);
    37 
    38   return ret_val;
    39 }
    40 
    41 void* zcalloc(size_t size, unsigned int count)
    42 {
    43   return zalloc(size*count);
    44 }
    4528
    4629/* From lib/time.c */
  • trunk/src/reglookup-recover.c

    r152 r157  
    258258{
    259259  void_stack* path_stack = void_stack_new(REGFI_MAX_DEPTH);
    260   const REGFI_HBIN* hbin;
    261260  REGFI_NK_REC* cur_ancestor;
    262261  char* ret_val;
    263   uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used;
    264   uint32 max_length;
     262  uint32 virt_offset, i, stack_size, ret_val_size, ret_val_used, offset;
     263  int32 max_size;
    265264  REGFI_BUFFER* path_element;
    266265 
     
    269268  ret_val_size = 1; /* NUL */
    270269  while(virt_offset != REGFI_OFFSET_NONE)
    271   { 
    272     hbin = regfi_lookup_hbin(f, virt_offset);
    273     if(hbin == NULL)
     270  {
     271    offset = virt_offset+REGFI_REGF_SIZE;
     272    max_size = regfi_calc_maxsize(f, offset);
     273    if(max_size < 0)
    274274      virt_offset = REGFI_OFFSET_NONE;
    275275    else
    276276    {
    277       max_length = hbin->block_size + hbin->file_off
    278         - (virt_offset+REGFI_REGF_SIZE);
    279       cur_ancestor = regfi_parse_nk(f, virt_offset+REGFI_REGF_SIZE,
    280                                     max_length, true);
     277      cur_ancestor = regfi_parse_nk(f, offset, max_size, true);
    281278      printMsgs(f);
    282279
     
    456453
    457454
    458 int extractDataCells(REGFI_FILE* f,
     455int extractDataCells(REGFI_FILE* file,
    459456                     range_list* unalloc_cells,
    460457                     range_list* unalloc_values)
     
    462459  const range_list_element* cur_elem;
    463460  REGFI_VK_REC* vk;
    464   const REGFI_HBIN* hbin;
     461  range_list* bd_cells;
    465462  REGFI_BUFFER data;
    466   uint32 i, off, data_offset, data_maxsize;
     463  uint32 i, j, offset, cell_length, length;
     464  int32 max_size;
     465  bool unalloc;
     466
     467  bd_cells = range_list_new();
     468  if(bd_cells == NULL)
     469    return 10;
    467470
    468471  for(i=0; i<range_list_size(unalloc_values); i++)
     
    471474    vk = (REGFI_VK_REC*)cur_elem->data;
    472475    if(vk == NULL)
    473       return 40;
    474 
    475     if(vk->data_size == 0)
    476       vk->data = NULL;
    477     else
    478     {
    479       off = vk->data_off+REGFI_REGF_SIZE;
     476      return 11;
     477
     478    length = vk->data_size;
     479    vk->data = NULL;
     480    if(vk->data_size != 0)
     481    {
     482      offset = vk->data_off+REGFI_REGF_SIZE;
    480483
    481484      if(vk->data_in_offset)
     485        data = regfi_parse_little_data(file, vk->data_off,
     486                                       length, false);
     487      else
    482488      {
    483         data = regfi_load_data(f, vk->type, vk->data_off,
    484                                vk->data_size, 4,
    485                                vk->data_in_offset, false);
     489        max_size = regfi_calc_maxsize(file, offset);
     490        if(max_size >= 0
     491           && regfi_parse_cell(file->fd, offset, NULL, 0,
     492                               &cell_length, &unalloc)
     493           && (cell_length & 0x00000007) == 0
     494           && cell_length <= max_size)
     495        {
     496          if(cell_length - 4 < length)
     497          {
     498            /* Multi-cell "big data" */
     499
     500            /* XXX: All big data records thus far have been 16 bytes long. 
     501             *      Should we check for this precise size instead of just
     502             *      relying upon the above check?
     503             */
     504            if (file->major_version >= 1 && file->minor_version >= 5)
     505            {
     506              /* Attempt to parse a big data record */
     507              data = regfi_load_big_data(file, offset, length,
     508                                         cell_length, bd_cells, false);
     509
     510              /* XXX: if this turns out NULL, should fall back to truncating cell */
     511              if(data.buf != NULL)
     512              {
     513                for(j=0; j<range_list_size(bd_cells); j++)
     514                {
     515                  cur_elem = range_list_get(bd_cells, j);
     516                  if(cur_elem == NULL)
     517                    return 20;
     518                  if(!range_list_has_range(unalloc_cells,
     519                                           cur_elem->offset,
     520                                           cur_elem->length))
     521                  {
     522                    fprintf(stderr,
     523                            "WARN: Successfully parsed big data at offset"
     524                            " 0x%.8X was rejected because some substructure"
     525                            " (offset=0x%.8X) is allocated or used in other"
     526                            " recovered structures.\n",
     527                            offset, cur_elem->offset);
     528                    talloc_free(data.buf);
     529                    data.buf = NULL;
     530                    data.len = 0;
     531                    break;
     532                  }
     533                }
     534               
     535                if(data.buf != NULL)
     536                {
     537                  for(j=0; j<range_list_size(bd_cells); j++)
     538                  {
     539                    cur_elem = range_list_get(bd_cells, j);
     540                    if(cur_elem == NULL)
     541                      return 21;
     542                   
     543                    if(!removeRange(unalloc_cells,
     544                                    cur_elem->offset,
     545                                    cur_elem->length))
     546                    { return 22; }
     547                  }
     548                }
     549              }
     550
     551            }
     552            else
     553            {
     554              fprintf(stderr,
     555                      "WARN: Data length (0x%.8X)"
     556                      " larger than remaining cell length (0x%.8X)"
     557                      " while parsing data record at offset 0x%.8X."
     558                      " Truncating...\n",
     559                      length, cell_length - 4, offset);
     560               length = cell_length - 4;
     561            }
     562          }
     563         
     564          /* Typical 1-cell data */
     565          if(range_list_has_range(unalloc_cells, offset, length))
     566          {
     567            data = regfi_parse_data(file, offset, length, false);
     568            if(data.buf != NULL)
     569              if(!removeRange(unalloc_cells, offset, length))
     570                return 30;
     571          }
     572        }
     573
    486574        vk->data = data.buf;
    487575        vk->data_size = data.len;
    488576      }
    489       else if(range_list_has_range(unalloc_cells, off, vk->data_size))
    490       {
    491         hbin = regfi_lookup_hbin(f, vk->data_off);
    492         if(hbin)
    493         {
    494           data_offset = vk->data_off+REGFI_REGF_SIZE;
    495           data_maxsize = hbin->block_size + hbin->file_off - data_offset;
    496           data = regfi_load_data(f, vk->type, data_offset,
    497                                  vk->data_size, data_maxsize,
    498                                  vk->data_in_offset, false);
    499           vk->data = data.buf;
    500           vk->data_size = data.len;
    501 
    502           if(vk->data != NULL)
    503           {
    504             /* XXX: The following may not make sense now in light of big data
    505              *      records.
    506              */
    507             /* XXX: This strict checking prevents partial recovery of data
    508              *      cells.  Also, see code for regfi_load_data and note that
    509              *      lengths indicated in VK records are sometimes just plain
    510              *      wrong.  Need a feedback mechanism to be more fuzzy with
    511              *      data cell lengths and the ranges removed.
    512              *
    513              *      The introduction of REGFI_BUFFER in regfi_load_data has
    514              *      fixed some of this.  Should review again with respect to
    515              *      the other issues mentioned above though.
    516              */
    517             /* A data record was recovered. Remove from unalloc_cells. */
    518             if(!removeRange(unalloc_cells, off, vk->data_size))
    519               return 50;
    520           }
    521         }
    522         else
    523           vk->data = NULL;
    524       }
    525     }
    526   }
    527 
     577    }
     578  }
     579
     580  range_list_free(bd_cells);
    528581  return 0;
    529582}
     
    590643  REGFI_NK_REC* nk;
    591644  REGFI_VK_REC* vk;
    592   const REGFI_HBIN* hbin;
    593645  const range_list_element* cur_elem;
    594   uint32 i, j, num_keys, off, values_length, max_length;
     646  uint32 i, j, num_keys, off, values_length;
     647  int32 max_size;
    595648
    596649  num_keys=range_list_size(unalloc_keys);
     
    604657    if(nk->num_values && (nk->values_off!=REGFI_OFFSET_NONE))
    605658    {
    606       hbin = regfi_lookup_hbin(f, nk->values_off);
    607      
    608       if(hbin != NULL)
     659      off = nk->values_off + REGFI_REGF_SIZE;
     660      max_size = regfi_calc_maxsize(f, off);
     661      if(max_size >= 0)
    609662      {
    610         off = nk->values_off + REGFI_REGF_SIZE;
    611         max_length = hbin->block_size + hbin->file_off - off;
    612663        nk->values = regfi_load_valuelist(f, off, nk->num_values,
    613                                           max_length, false);
     664                                          max_size, false);
    614665        if(nk->values != NULL && nk->values->elements != NULL)
    615666        {
Note: See TracChangeset for help on using the changeset viewer.