Skip to content

Commit 8f77de6

Browse files
author
Seppo Takalo
committed
TDBStore safety check: Erase if there is valid keys on the free space.
In case our are contains data from previous reset() or reset_area(), we might end up in the situation where free space contains valid key headers, but we have not erased that area yet. This can cause failures if the deinit() and init() because new scan of that area would continue as long as keys are found. This causes keys on the not-yet-erased area to be included in the new instance of TDBStore. To prevent this failure, check after each key-write that our free space does not contain valid key headers. Also make sure that we erase one program unit sector over the master record. If we erased just the master record,first key might is still there, causing next init() to find it. Extend erase area by one program unit, so that build_ram_table() won't find any keys.
1 parent a1cddba commit 8f77de6

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

features/storage/kvstore/tdbstore/TDBStore.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ TDBStore::~TDBStore()
148148

149149
int TDBStore::read_area(uint8_t area, uint32_t offset, uint32_t size, void *buf)
150150
{
151+
//Check that we are not crossing area boundary
152+
if (offset + size > _size) {
153+
return MBED_ERROR_READ_FAILED;
154+
}
151155
int os_ret = _buff_bd->read(buf, _area_params[area].address + offset, size);
152156

153157
if (os_ret) {
@@ -649,6 +653,15 @@ int TDBStore::set_finalize(set_handle_t handle)
649653

650654
_free_space_offset = align_up(ih->bd_curr_offset, _prog_size);
651655

656+
// Safety check: If there seems to be valid keys on the free space
657+
// we should erase one sector more, just to ensure that in case of power failure
658+
// next init() would not extend the scan phase to that section as well.
659+
os_ret = read_record(_active_area, _free_space_offset, 0, 0, 0, actual_data_size, 0,
660+
false, false, false, false, hash, flags, next_offset);
661+
if (os_ret == MBED_SUCCESS) {
662+
check_erase_before_write(_active_area, _free_space_offset, sizeof(record_header_t));
663+
}
664+
652665
end:
653666
if ((need_gc) && (ih->bd_base_offset != _master_record_offset)) {
654667
garbage_collection();
@@ -972,6 +985,7 @@ int TDBStore::increment_max_keys(void **ram_table)
972985
// Reallocate ram table with new size
973986
ram_table_entry_t *old_ram_table = (ram_table_entry_t *) _ram_table;
974987
ram_table_entry_t *new_ram_table = new ram_table_entry_t[_max_keys + 1];
988+
memset(new_ram_table, 0, sizeof(ram_table_entry_t)*(_max_keys + 1));
975989

976990
// Copy old content to new table
977991
memcpy(new_ram_table, old_ram_table, sizeof(ram_table_entry_t) * _max_keys);
@@ -1018,6 +1032,7 @@ int TDBStore::init()
10181032
_max_keys = initial_max_keys;
10191033

10201034
ram_table = new ram_table_entry_t[_max_keys];
1035+
memset(ram_table, 0, sizeof(ram_table_entry_t) * _max_keys);
10211036
_ram_table = ram_table;
10221037
_num_keys = 0;
10231038

@@ -1211,7 +1226,7 @@ int TDBStore::reset()
12111226
_num_keys = 0;
12121227
_free_space_offset = _master_record_offset;
12131228
_active_area_version = 1;
1214-
1229+
memset(_ram_table, 0, sizeof(ram_table_entry_t) * _max_keys);
12151230
// Write an initial master record on active area
12161231
ret = write_master_record(_active_area, _active_area_version, _free_space_offset);
12171232

features/storage/kvstore/tdbstore/TDBStore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ class TDBStore : public KVStore {
365365
*
366366
* @param[in] area Area.
367367
* @param[in] offset Offset of record in area.
368-
* @param[in] key Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
369-
* @param[in] data_buf Data buffer.
368+
* @param[out] key Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
369+
* @param[out] data_buf Data buffer.
370370
* @param[in] data_buf_size Data buffer size.
371371
* @param[out] actual_data_size Actual data size.
372372
* @param[in] data_offset Offset in data.

0 commit comments

Comments
 (0)