Changeset 145 for trunk


Ignore:
Timestamp:
02/15/09 18:36:20 (15 years ago)
Author:
tim
Message:

decoupled value parsing from key parsing

moved linking of value records and data records up to the load layer

rewrote key/value/data linking algorithm in reglookup-recover which improved recovery results

fixed a NULL pointer dereference in range_list.c

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Makefile

    r144 r145  
    1111
    1212CC=gcc
    13 #OPTS=-std=gnu89 -pedantic -Wall -ggdb
    14 OPTS=-std=gnu89 -pedantic -Wall
     13OPTS=-std=gnu89 -pedantic -Wall -ggdb
     14#OPTS=-std=gnu89 -pedantic -Wall
    1515INC=-I/usr/local/include
    1616LIB=-L/usr/local/lib -lm
  • trunk/include/regfi.h

    r143 r145  
    191191
    192192
    193 typedef struct
     193typedef struct _regfi_subkey_list
    194194{
    195195  /* Real offset of this record's cell in the file */
     
    210210  bool recursive_type; 
    211211} REGFI_SUBKEY_LIST;
     212
     213
     214typedef uint32 REGFI_VALUE_LIST_ELEM;
     215typedef struct _regfi_value_list
     216{
     217  /* Actual number of values referenced by this list. 
     218   * May differ from parent key's num_values if there were parsing errors.
     219   */
     220  uint32 num_values;
     221
     222  REGFI_VALUE_LIST_ELEM* elements;
     223} REGFI_VALUE_LIST;
    212224
    213225
     
    269281
    270282  /* link in the other records here */
    271   REGFI_VK_REC** values;
     283  REGFI_VALUE_LIST* values;
    272284  REGFI_SUBKEY_LIST* subkeys;
    273285 
     
    427439/* Middle-layer structure caching, loading, and linking */
    428440/********************************************************/
    429 REGFI_HBIN*           regfi_lookup_hbin(REGFI_FILE* file, uint32 offset);
     441REGFI_HBIN*           regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset);
    430442REGFI_NK_REC*         regfi_load_key(REGFI_FILE* file, uint32 offset,
    431443                                     bool strict);
     
    433445                                            uint32 num_keys, uint32 max_size,
    434446                                            bool strict);
    435 REGFI_VK_REC**        regfi_load_valuelist(REGFI_FILE* file, uint32 offset,
     447REGFI_VK_REC*         regfi_load_value(REGFI_FILE* file, uint32 offset,
     448                                       bool strict);
     449REGFI_VALUE_LIST*     regfi_load_valuelist(REGFI_FILE* file, uint32 offset,
    436450                                           uint32 num_values, uint32 max_size,
    437451                                           bool strict);
     
    465479                                     uint32 max_size, bool strict);
    466480
    467 uint8*                regfi_parse_data(REGFI_FILE* file, uint32 offset,
     481uint8*                regfi_parse_data(REGFI_FILE* file,
     482                                       uint32 data_type, uint32 offset,
    468483                                       uint32 length, uint32 max_size,
    469                                        bool strict);
     484                                       bool data_in_offset, bool strict);
    470485
    471486REGFI_SK_REC*         regfi_parse_sk(REGFI_FILE* file, uint32 offset,
  • trunk/lib/range_list.c

    r122 r145  
    265265  range_list_element* elem;
    266266
     267  if(rl->size == 0)
     268    return -1;
     269
    267270  if((offset < rl->elements[0]->offset)
    268271     || (offset > rl->elements[rl->size-1]->offset
    269272         + rl->elements[rl->size-1]->length))
    270     return -1;
     273    return -2;
    271274
    272275  prev_idx = range_list_find_previous(rl, offset);
     
    275278    return prev_idx;
    276279
    277   return -2;
     280  return -3;
    278281}
    279282
  • trunk/lib/regfi.c

    r143 r145  
    475475 * The offset is a virtual file offset.
    476476 *******************************************************************/
    477 static bool regfi_offset_in_hbin(REGFI_HBIN* hbin, uint32 offset)
     477static bool regfi_offset_in_hbin(REGFI_HBIN* hbin, uint32 voffset)
    478478{
    479479  if(!hbin)
    480480    return false;
    481481
    482   if((offset > hbin->first_hbin_off)
    483      && (offset < (hbin->first_hbin_off + hbin->block_size)))
     482  if((voffset > hbin->first_hbin_off)
     483     && (voffset < (hbin->first_hbin_off + hbin->block_size)))
    484484    return true;
    485485               
     
    493493 * block for it.  NULL if one doesn't exist.
    494494 *******************************************************************/
    495 REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 offset)
    496 {
    497   return (REGFI_HBIN*)range_list_find_data(file->hbins, offset+REGFI_REGF_SIZE);
     495REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset)
     496{
     497  return (REGFI_HBIN*)range_list_find_data(file->hbins, voffset+REGFI_REGF_SIZE);
    498498}
    499499
     
    870870
    871871
    872 uint32* regfi_parse_valuelist(REGFI_FILE* file, uint32 offset,
    873                               uint32 num_values, bool strict)
    874 {
    875   uint32* ret_val;
     872REGFI_VALUE_LIST* regfi_parse_valuelist(REGFI_FILE* file, uint32 offset,
     873                                        uint32 num_values, bool strict)
     874{
     875  REGFI_VALUE_LIST* ret_val;
    876876  uint32 i, cell_length, length, read_len;
    877877  bool unalloc;
     
    886886  if(cell_length != (cell_length & 0xFFFFFFF8))
    887887  {
     888    regfi_add_message(file, REGFI_MSG_WARN, "Cell length not a multiple of 8"
     889                      " while parsing value list at offset 0x%.8X.", offset);
    888890    if(strict)
    889891      return NULL;
    890892    cell_length = cell_length & 0xFFFFFFF8;
    891893  }
     894
    892895  if((num_values * sizeof(uint32)) > cell_length-sizeof(uint32))
    893896  {
    894897    regfi_add_message(file, REGFI_MSG_WARN, "Too many values found"
    895898                      " while parsing value list at offset 0x%.8X.", offset);
    896     /* XXX: During non-strict, should reduce num_values appropriately and
    897      *      continue instead of bailing out.
    898      */
    899     return NULL;
     899    if(strict)
     900      return NULL;
     901    num_values = cell_length/sizeof(uint32) - sizeof(uint32);
    900902  }
    901903
    902904  read_len = num_values*sizeof(uint32);
    903   ret_val = (uint32*)malloc(read_len);
     905  ret_val = (REGFI_VALUE_LIST*)malloc(sizeof(REGFI_VALUE_LIST));
    904906  if(ret_val == NULL)
    905907    return NULL;
    906908
     909  ret_val->elements = (REGFI_VALUE_LIST_ELEM*)malloc(read_len);
     910  if(ret_val->elements == NULL)
     911  {
     912    free(ret_val);
     913    return NULL;
     914  }
     915  ret_val->num_values = num_values;
     916
    907917  length = read_len;
    908   if((regfi_read(file->fd, (uint8*)ret_val, &length) != 0) || length != read_len)
     918  if((regfi_read(file->fd, (uint8*)ret_val->elements, &length) != 0)
     919     || length != read_len)
    909920  {
    910921    regfi_add_message(file, REGFI_MSG_ERROR, "Failed to read value pointers"
    911922                      " while parsing value list at offset 0x%.8X.", offset);
     923    free(ret_val->elements);
    912924    free(ret_val);
    913925    return NULL;
     
    917929  {
    918930    /* Fix endianness */
    919     ret_val[i] = IVAL(&ret_val[i], 0);
     931    ret_val->elements[i] = IVAL(&ret_val->elements[i], 0);
    920932
    921933    /* Validate the first num_values values to ensure they make sense */
    922934    if(strict)
    923935    {
    924       if((ret_val[i] + REGFI_REGF_SIZE > file->file_length)
    925          || ((ret_val[i] & 0xFFFFFFF8) != ret_val[i]))
     936      /* XXX: Need to revisit this file length check when we start dealing
     937       *      with partial files. */
     938      if((ret_val->elements[i] + REGFI_REGF_SIZE > file->file_length)
     939         || ((ret_val->elements[i] & 0xFFFFFFF8) != ret_val->elements[i]))
    926940      {
    927         regfi_add_message(file, REGFI_MSG_ERROR, "Invalid value pointer"
     941        regfi_add_message(file, REGFI_MSG_WARN, "Invalid value pointer"
    928942                          " (0x%.8X) found while parsing value list at offset"
    929                           " 0x%.8X.", ret_val[i], offset);
     943                          " 0x%.8X.", ret_val->elements[i], offset);
     944        free(ret_val->elements);
    930945        free(ret_val);
    931946        return NULL;
     
    940955
    941956/******************************************************************************
     957 ******************************************************************************/
     958REGFI_VK_REC* regfi_load_value(REGFI_FILE* file, uint32 offset, bool strict)
     959{
     960  REGFI_VK_REC* ret_val = NULL;
     961  REGFI_HBIN* hbin;
     962  uint32 data_offset, data_maxsize;
     963
     964  hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
     965  if(!hbin)
     966    return NULL;
     967 
     968  ret_val = regfi_parse_vk(file, offset,
     969                           hbin->block_size + hbin->file_off - offset, strict);
     970
     971  if(ret_val == NULL)
     972    return NULL;
     973
     974  if(ret_val->data_size == 0)
     975    ret_val->data = NULL;
     976  else
     977  {
     978    if(ret_val->data_in_offset)
     979    {
     980      ret_val->data = regfi_parse_data(file, ret_val->type, ret_val->data_off,
     981                                       ret_val->data_size, 4,
     982                                       ret_val->data_in_offset, strict);
     983    }
     984    else
     985    {
     986      hbin = regfi_lookup_hbin(file, ret_val->data_off);
     987      if(hbin)
     988      {
     989        data_offset = ret_val->data_off+REGFI_REGF_SIZE;
     990        data_maxsize = hbin->block_size + hbin->file_off - data_offset;
     991        ret_val->data = regfi_parse_data(file, ret_val->type, data_offset,
     992                                         ret_val->data_size, data_maxsize,
     993                                         ret_val->data_in_offset, strict);
     994      }
     995      else
     996      {
     997        regfi_add_message(file, REGFI_MSG_WARN, "Could not find HBIN for data"
     998                          " while parsing VK record at offset 0x%.8X.",
     999                          ret_val->offset);
     1000        ret_val->data = NULL;
     1001      }
     1002    }
     1003
     1004    if(ret_val->data == NULL)
     1005    {
     1006      regfi_add_message(file, REGFI_MSG_WARN, "Could not parse data record"
     1007                        " while parsing VK record at offset 0x%.8X.",
     1008                        ret_val->offset);
     1009    }
     1010  }
     1011
     1012  return ret_val;
     1013}
     1014
     1015
     1016/******************************************************************************
    9421017 * If !strict, the list may contain NULLs, VK records may point to NULL.
    9431018 ******************************************************************************/
    944 REGFI_VK_REC** regfi_load_valuelist(REGFI_FILE* file, uint32 offset,
    945                                    uint32 num_values, uint32 max_size,
    946                                    bool strict)
    947 {
    948   REGFI_VK_REC** ret_val;
    949   REGFI_HBIN* hbin;
    950   uint32 i, vk_offset, vk_max_length, usable_num_values;
    951   uint32* voffsets;
     1019REGFI_VALUE_LIST* regfi_load_valuelist(REGFI_FILE* file, uint32 offset,
     1020                                       uint32 num_values, uint32 max_size,
     1021                                       bool strict)
     1022{
     1023  uint32 usable_num_values;
    9521024
    9531025  if((num_values+1) * sizeof(uint32) > max_size)
    9541026  {
     1027    regfi_add_message(file, REGFI_MSG_WARN, "Number of values indicated by"
     1028                      " parent key (%d) would cause cell to straddle HBIN"
     1029                      " boundary while loading value list at offset"
     1030                      " 0x%.8X.", num_values, offset);
    9551031    if(strict)
    9561032      return NULL;
     
    9601036    usable_num_values = num_values;
    9611037
    962   voffsets = regfi_parse_valuelist(file, offset, usable_num_values, strict);
    963   if(voffsets == NULL)
    964     return NULL;
    965 
    966   ret_val = (REGFI_VK_REC**)zalloc(sizeof(REGFI_VK_REC*) * usable_num_values);
    967   if(ret_val == NULL)
    968   {
    969     free(voffsets);
    970     return NULL;
    971   }
    972  
    973   for(i=0; i < usable_num_values; i++)
    974   {
    975     hbin = regfi_lookup_hbin(file, voffsets[i]);
    976     if(!hbin)
    977     {
    978       free(voffsets);
    979       free(ret_val);
    980       return NULL;
    981     }
    982 
    983     vk_offset =  voffsets[i] + REGFI_REGF_SIZE;
    984     vk_max_length = hbin->block_size + hbin->file_off - vk_offset;
    985     ret_val[i] = regfi_parse_vk(file, vk_offset, vk_max_length, strict);
    986     if(ret_val[i] == NULL)
    987     { /* If we're being strict, throw out the whole list.
    988        * Otherwise, let it be NULL.
    989        */
    990       if(strict)
    991       {
    992         free(voffsets);
    993         free(ret_val);
    994         return NULL;
    995       }
    996     }
    997   }
    998 
    999   free(voffsets);
    1000   return ret_val;
     1038  return regfi_parse_valuelist(file, offset, usable_num_values, strict);
    10011039}
    10021040
     
    10511089      nk->values = regfi_load_valuelist(file, off, nk->num_values, max_length,
    10521090                                        true);
    1053       if(strict && nk->values == NULL)
     1091      if(nk->values == NULL)
    10541092      {
    1055         regfi_add_message(file, REGFI_MSG_ERROR, "Could not load value list"
    1056                           " for NK record at offset 0x%.8X.",
    1057                           offset);
    1058         free(nk);
    1059         return NULL;
     1093        regfi_add_message(file, REGFI_MSG_WARN, "Could not load value list"
     1094                          " for NK record at offset 0x%.8X.", offset);
     1095        if(strict)
     1096        {
     1097          free(nk);
     1098          return NULL;
     1099        }
    10601100      }
    1061 
    10621101    }
    10631102  }
     
    12711310void regfi_key_free(REGFI_NK_REC* nk)
    12721311{
    1273   uint32 i;
    1274  
    12751312  if((nk->values != NULL) && (nk->values_off!=REGFI_OFFSET_NONE))
    12761313  {
    1277     for(i=0; i < nk->num_values; i++)
    1278     {
    1279       if(nk->values[i]->valuename != NULL)
    1280         free(nk->values[i]->valuename);
    1281       if(nk->values[i]->data != NULL)
    1282         free(nk->values[i]->data);
    1283       free(nk->values[i]);
    1284     }
     1314    if(nk->values->elements != NULL)
     1315      free(nk->values->elements);
    12851316    free(nk->values);
    12861317  }
     
    16281659{
    16291660  REGFI_VK_REC* ret_val = NULL;
    1630   if(i->cur_value < i->cur_key->num_values)
    1631     ret_val = i->cur_key->values[i->cur_value];
     1661  uint32 voffset;
     1662
     1663  if(i->cur_key->values != NULL && i->cur_key->values->elements != NULL)
     1664  {
     1665    if(i->cur_value < i->cur_key->values->num_values)
     1666    {
     1667      voffset = i->cur_key->values->elements[i->cur_value];
     1668      ret_val = regfi_load_value(i->f, voffset+REGFI_REGF_SIZE, true);
     1669    }
     1670  }
    16321671
    16331672  return ret_val;
     
    20502089 *******************************************************************/
    20512090REGFI_VK_REC* regfi_parse_vk(REGFI_FILE* file, uint32 offset,
    2052                             uint32 max_size, bool strict)
     2091                             uint32 max_size, bool strict)
    20532092{
    20542093  REGFI_VK_REC* ret_val;
    2055   REGFI_HBIN *hbin;
    20562094  uint8 vk_header[REGFI_VK_MIN_LENGTH];
    20572095  uint32 raw_data_size, length, cell_length;
    2058   uint32 data_offset, data_maxsize;
    20592096  bool unalloc = false;
    20602097
     
    21592196  }
    21602197
    2161   if(ret_val->data_size == 0)
    2162     ret_val->data = NULL;
    2163   else
    2164   {
    2165     if(ret_val->data_in_offset)
    2166     {
    2167       ret_val->data = regfi_parse_data(file, ret_val->data_off,
    2168                                        raw_data_size, 4, strict);
    2169     }
    2170     else
    2171     {
    2172       hbin = regfi_lookup_hbin(file, ret_val->data_off);
    2173       if(hbin)
    2174       {
    2175         data_offset = ret_val->data_off+REGFI_REGF_SIZE;
    2176         data_maxsize = hbin->block_size + hbin->file_off - data_offset;
    2177         ret_val->data = regfi_parse_data(file, data_offset, raw_data_size,
    2178                                          data_maxsize, strict);
    2179        
    2180       }
    2181       else
    2182       {
    2183         regfi_add_message(file, REGFI_MSG_WARN, "Could not find hbin for data"
    2184                           " while parsing VK record at offset 0x%.8X.", offset);
    2185         ret_val->data = NULL;
    2186       }
    2187     }
    2188 
    2189     if(ret_val->data == NULL)
    2190     {
    2191       regfi_add_message(file, REGFI_MSG_WARN, "Could not parse data record"
    2192                         " while parsing VK record at offset 0x%.8X.", offset);
    2193     }
    2194   }
    2195 
    21962198  return ret_val;
    21972199}
    21982200
    21992201
    2200 uint8* regfi_parse_data(REGFI_FILE* file, uint32 offset, uint32 length,
    2201                         uint32 max_size, bool strict)
     2202uint8* regfi_parse_data(REGFI_FILE* file,
     2203                        uint32 data_type, uint32 offset,
     2204                        uint32 length, uint32 max_size,
     2205                        bool data_in_offset, bool strict)
    22022206{
    22032207  uint8* ret_val;
     
    22072211
    22082212  /* The data is typically stored in the offset if the size <= 4 */
    2209   if (length & REGFI_VK_DATA_IN_OFFSET)
    2210   {
    2211     length = length & ~REGFI_VK_DATA_IN_OFFSET;
     2213  if(data_in_offset)
     2214  {
    22122215    if(length > 4)
    22132216    {
     
    22442247    if(cell_length > max_size)
    22452248    {
    2246       regfi_add_message(file, REGFI_MSG_WARN, "Cell extends past hbin boundary"
    2247                         " while parsing data record at offset 0x%.8X.", 
     2249      regfi_add_message(file, REGFI_MSG_WARN, "Cell extends past HBIN boundary"
     2250                        " while parsing data record at offset 0x%.8X.",
    22482251                        offset);
    22492252      if(strict)
  • trunk/src/reglookup-recover.c

    r143 r145  
    416416
    417417
     418int extractVKs(REGFI_FILE* f,
     419               range_list* unalloc_cells,
     420               range_list* unalloc_values)
     421{
     422  const range_list_element* cur_elem;
     423  REGFI_VK_REC* vk;
     424  uint32 i, j;
     425
     426  for(i=0; i < range_list_size(unalloc_cells); i++)
     427  {
     428    printMsgs(f);
     429    cur_elem = range_list_get(unalloc_cells, i);
     430    for(j=0; j <= cur_elem->length; j+=8)
     431    {
     432      vk = regfi_parse_vk(f, cur_elem->offset+j,
     433                           cur_elem->length-j, false);
     434      printMsgs(f);
     435
     436      if(vk != NULL)
     437      {
     438        if(!range_list_add(unalloc_values, vk->offset,
     439                           vk->cell_size, vk))
     440        {
     441          fprintf(stderr, "ERROR: Couldn't add value to unalloc_values.\n");
     442          return 20;
     443        }
     444        j+=vk->cell_size-8;
     445      }
     446    }
     447  }
     448
     449  /* Remove value ranges from the unalloc_cells before we continue. */
     450  for(i=0; i<range_list_size(unalloc_values); i++)
     451  {
     452    cur_elem = range_list_get(unalloc_values, i);
     453    if(!removeRange(unalloc_cells, cur_elem->offset, cur_elem->length))
     454      return 30;
     455  }
     456
     457  return 0;
     458}
     459
     460
     461int extractDataCells(REGFI_FILE* f,
     462                     range_list* unalloc_cells,
     463                     range_list* unalloc_values)
     464{
     465  const range_list_element* cur_elem;
     466  REGFI_VK_REC* vk;
     467  REGFI_HBIN* hbin;
     468  uint32 i, off, data_offset, data_maxsize;
     469
     470  for(i=0; i<range_list_size(unalloc_values); i++)
     471  {
     472    cur_elem = range_list_get(unalloc_values, i);
     473    vk = (REGFI_VK_REC*)cur_elem->data;
     474    if(vk == NULL)
     475      return 40;
     476
     477    if(vk->data_size == 0)
     478      vk->data = NULL;
     479    else
     480    {
     481      off = vk->data_off+REGFI_REGF_SIZE;
     482
     483      if(vk->data_in_offset)
     484      {
     485        vk->data = regfi_parse_data(f, vk->type, vk->data_off,
     486                                    vk->data_size, 4,
     487                                    vk->data_in_offset, false);
     488      }
     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          vk->data = regfi_parse_data(f, vk->type, data_offset,
     497                                      vk->data_size, data_maxsize,
     498                                      vk->data_in_offset, false);
     499          if(vk->data != NULL)
     500          {
     501            /* XXX: This strict checking prevents partial recovery of data
     502             *      cells.  Also, see code for regfi_parse_data and note that
     503             *      lengths indicated in VK records are sometimes just plain
     504             *      wrong.  Need a feedback mechanism to be more fuzzy with
     505             *      data cell lengths and the ranges removed.
     506             */
     507            /* A data record was recovered. Remove from unalloc_cells. */
     508            if(!removeRange(unalloc_cells, off, vk->data_size))
     509              return 50;
     510          }
     511        }
     512        else
     513          vk->data = NULL;
     514      }
     515    }
     516  }
     517
     518  return 0;
     519}
     520
     521
    418522/* NOTE: unalloc_keys should be an empty range_list. */
    419523int extractKeys(REGFI_FILE* f,
     
    459563}
    460564
    461 
    462565int extractValueLists(REGFI_FILE* f,
    463566                      range_list* unalloc_cells,
    464                       range_list* unalloc_keys)
     567                      range_list* unalloc_keys,
     568                      range_list* unalloc_linked_values)
    465569{
    466570  REGFI_NK_REC* nk;
     571  REGFI_VK_REC* vk;
    467572  REGFI_HBIN* hbin;
    468573  const range_list_element* cur_elem;
     
    485590        off = nk->values_off + REGFI_REGF_SIZE;
    486591        max_length = hbin->block_size + hbin->file_off - off;
    487         /* XXX: This is a hack.  We parse all value-lists, VK records,
    488          *      and data records without regard for current allocation status. 
    489          *      On the off chance that such a record correctly parsed but is
    490          *      actually a reallocated structure used by something else, we
    491          *      simply prune it after the fact.  Would be faster to check this
    492          *      up front somehow.
    493          */
    494         nk->values = regfi_load_valuelist(f, off, nk->num_values, max_length,
    495                                           false);
    496         values_length = (nk->num_values+1)*sizeof(uint32);
    497         if(values_length != (values_length & 0xFFFFFFF8))
    498           values_length = (values_length & 0xFFFFFFF8) + 8;
    499 
    500         if(nk->values != NULL)
     592        nk->values = regfi_load_valuelist(f, off, nk->num_values,
     593                                          max_length, false);
     594        if(nk->values != NULL && nk->values->elements != NULL)
    501595        {
     596          /* Number of elements in the value list may be shorter than advertised
     597           * by NK record due to cell truncation.  We'll consider this valid and
     598           * only throw out the whole value list if it bleeds into an already
     599           * parsed structure.
     600           */
     601          values_length = (nk->values->num_values+1)*sizeof(uint32);
     602          if(values_length != (values_length & 0xFFFFFFF8))
     603            values_length = (values_length & 0xFFFFFFF8) + 8;
     604
    502605          if(!range_list_has_range(unalloc_cells, off, values_length))
    503606          { /* We've parsed a values-list which isn't in the unallocated list,
    504              * so prune it. 
     607             * so prune it.
    505608             */
    506             for(j=0; j<nk->num_values; j++)
    507             {
    508               if(nk->values[j] != NULL)
    509               {
    510                 if(nk->values[j]->data != NULL)
    511                   free(nk->values[j]->data);
    512                 free(nk->values[j]);
    513               }
    514             }
     609            free(nk->values->elements);
    515610            free(nk->values);
    516611            nk->values = NULL;
     
    523618              return 20;
    524619
    525             for(j=0; j < nk->num_values; j++)
     620            for(j=0; j < nk->values->num_values; j++)
    526621            {
    527               if(nk->values[j] != NULL)
     622              /* Don't bother to restrict cell length here, since we'll
     623               * check our unalloc_cells range_list later.
     624               */
     625              vk = regfi_parse_vk(f, nk->values->elements[j]+REGFI_REGF_SIZE,
     626                                  0x7FFFFFFF, false);
     627              printMsgs(f);
     628             
     629              if(vk != NULL)
    528630              {
    529                 if(!range_list_has_range(unalloc_cells, nk->values[j]->offset,
    530                                          nk->values[j]->cell_size))
    531                 { /* We've parsed a value which isn't in the unallocated list,
    532                    * so prune it.
    533                    */
    534                   if(nk->values[j]->data != NULL)
    535                     free(nk->values[j]->data);
    536                   free(nk->values[j]);
    537                   nk->values[j] = NULL;
     631                if(range_list_has_range(unalloc_cells,
     632                                        vk->offset, vk->cell_size))
     633                {
     634                  if(!range_list_add(unalloc_linked_values, vk->offset,
     635                                     vk->cell_size, vk))
     636                  {
     637                    free(vk);
     638                    return 30;
     639                  }
     640
     641                  if(!removeRange(unalloc_cells, vk->offset, vk->cell_size))
     642                    return 40;
    538643                }
    539644                else
    540                 {
    541                   /* A VK record was recovered.  Remove from unalloc_cells
    542                    * and inspect data.
    543                    */
    544                   if(!removeRange(unalloc_cells, nk->values[j]->offset,
    545                                   nk->values[j]->cell_size))
    546                     return 21;
    547 
    548                   /* Don't bother pruning or removing from unalloc_cells if
    549                    * there is no data, or it is stored in the offset.
    550                    */
    551                   if(nk->values[j]->data != NULL && !nk->values[j]->data_in_offset)
    552                   {
    553                     off = nk->values[j]->data_off+REGFI_REGF_SIZE;
    554                     if(!range_list_has_range(unalloc_cells, off,
    555                                              nk->values[j]->data_size))
    556                     { /* We've parsed a data cell which isn't in the unallocated
    557                        * list, so prune it.
    558                        */
    559                       free(nk->values[j]->data);
    560                       nk->values[j]->data = NULL;
    561                     }
    562                     else
    563                     { /*A data record was recovered. Remove from unalloc_cells.*/
    564                       if(!removeRange(unalloc_cells, off,
    565                                       nk->values[j]->data_size))
    566                         return 22;
    567                     }
    568                   }
    569                 }
     645                  free(vk);
    570646              }
    571647            }
     
    579655}
    580656
    581 
    582 /* NOTE: unalloc_values should be an empty range_list. */
    583 int extractValues(REGFI_FILE* f,
    584                   range_list* unalloc_cells,
    585                   range_list* unalloc_values)
    586 {
    587   const range_list_element* cur_elem;
    588   REGFI_VK_REC* vk;
    589   uint32 i, j, off;
    590 
    591   for(i=0; i < range_list_size(unalloc_cells); i++)
    592   {
    593     printMsgs(f);
    594     cur_elem = range_list_get(unalloc_cells, i);
    595     for(j=0; j <= cur_elem->length; j+=8)
    596     {
    597       vk = regfi_parse_vk(f, cur_elem->offset+j,
    598                            cur_elem->length-j, false);
    599       printMsgs(f);
    600 
    601       if(vk != NULL)
    602       {
    603         if(!range_list_add(unalloc_values, vk->offset,
    604                            vk->cell_size, vk))
    605         {
    606           fprintf(stderr, "ERROR: Couldn't add value to unalloc_values.\n");
    607           return 20;
    608         }
    609         j+=vk->cell_size-8;
    610       }
    611     }
    612   }
    613  
    614   /* Remove value ranges from the unalloc_cells before we continue. */
    615   for(i=0; i<range_list_size(unalloc_values); i++)
    616   {
    617     cur_elem = range_list_get(unalloc_values, i);
    618     if(!removeRange(unalloc_cells, cur_elem->offset, cur_elem->length))
    619       return 30;
    620   }
    621 
    622   /* Now see if the data associated with each value is intact */
    623   for(i=0; i<range_list_size(unalloc_values); i++)
    624   {
    625     cur_elem = range_list_get(unalloc_values, i);
    626     vk = (REGFI_VK_REC*)cur_elem->data;
    627     if(vk == NULL)
    628       return 40;
    629 
    630     if(vk->data != NULL && !vk->data_in_offset)
    631     {
    632       off = vk->data_off+REGFI_REGF_SIZE;
    633       if(!range_list_has_range(unalloc_cells, off, vk->data_size))
    634       { /* We've parsed a data cell which isn't in the unallocated
    635          * list, so prune it.
    636          */
    637         free(vk->data);
    638         vk->data = NULL;
    639       }
    640       else
    641       { /*A data record was recovered. Remove from unalloc_cells.*/
    642         if(!removeRange(unalloc_cells, off, vk->data_size))
    643           return 50;
    644       }
    645     }
    646   }
    647 
    648   return 0;
    649 }
    650657
    651658
     
    699706  range_list* unalloc_cells;
    700707  range_list* unalloc_keys;
     708  range_list* unalloc_linked_values;
    701709  range_list* unalloc_values;
    702710  range_list* unalloc_sks;
     
    707715  REGFI_VK_REC* tmp_value;
    708716  uint32 argi, arge, i, j, ret, num_unalloc_keys;
    709   /* uint32 test_offset;*/
    710717 
    711718  /* Process command line arguments */
     
    772779    return 10;
    773780
     781  unalloc_linked_values = range_list_new();
     782  if(unalloc_linked_values == NULL)
     783    return 10;
     784
    774785  unalloc_values = range_list_new();
    775786  if(unalloc_values == NULL)
     
    787798  }
    788799
    789   ret = extractValueLists(f, unalloc_cells, unalloc_keys);
     800  ret = extractValueLists(f, unalloc_cells, unalloc_keys,unalloc_linked_values);
    790801  if(ret != 0)
    791802  {
     
    794805  }
    795806
    796   /* Carve any orphan values and associated data */
    797   ret = extractValues(f, unalloc_cells, unalloc_values);
     807  /* Carve any orphan values */
     808  ret = extractVKs(f, unalloc_cells, unalloc_values);
    798809  if(ret != 0)
    799810  {
    800     fprintf(stderr, "ERROR: extractValues() failed with %d.\n", ret);
     811    fprintf(stderr, "ERROR: extractVKs() failed with %d.\n", ret);
    801812    return ret;
    802813  }
    803814
     815  /* Carve any data associated with VK records */
     816  ret = extractDataCells(f, unalloc_cells, unalloc_linked_values);
     817  if(ret != 0)
     818  {
     819    fprintf(stderr, "ERROR: extractDataCells() failed with %d.\n", ret);
     820    return ret;
     821  }
     822  ret = extractDataCells(f, unalloc_cells, unalloc_values);
     823  if(ret != 0)
     824  {
     825    fprintf(stderr, "ERROR: extractDataCells() failed with %d.\n", ret);
     826    return ret;
     827  }
     828 
    804829  /* Carve any SK records */
    805830  ret = extractSKs(f, unalloc_cells, unalloc_sks);
     
    832857 
    833858  /* Now start the output */
    834 
    835859  for(i=0; i < num_unalloc_keys; i++)
    836860  {
     
    850874
    851875      sprintf(tmp_path, "%s/%s", parent_paths[i], tmp_name);
    852       for(j=0; j < tmp_key->num_values; j++)
     876      for(j=0; j < tmp_key->values->num_values; j++)
    853877      {
    854         tmp_value = tmp_key->values[j];
     878        tmp_value =
     879          (REGFI_VK_REC*)range_list_find_data(unalloc_linked_values,
     880                                              tmp_key->values->elements[j]
     881                                              + REGFI_REGF_SIZE);
    855882        if(tmp_value != NULL)
    856883          printValue(f, tmp_value, tmp_path);
Note: See TracChangeset for help on using the changeset viewer.