Changeset 145 for trunk/lib


Ignore:
Timestamp:
02/15/09 18:36:20 (16 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/lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • 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)
Note: See TracChangeset for help on using the changeset viewer.