mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-02 19:02:00 +00:00
fix(companion): pack and history files from the card checked, contact loops skip the reserved slots, small UI fixes
- L2 vector packs: a damaged count can't wrap the index size, and an entry pointing past the file is refused. - L2 map share-target list: sized for 40 long channel names and 16 favourites (it could overflow), off the stack. - L2 SD history: a file with an unreadable header is set aside as .bad instead of written over; Delete message history takes those too. - Contact lookups by key or hash start after the reserved anon slots (an empty one matched a 00 hop hash with a blank name); MessagesScreen uses contactctl::hopName(). - Nearby keeps its selection by public key: deleting a contact shifts the table. - ui-new Live Share target cycle holds every channel and favourite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -177,7 +177,12 @@ public:
|
||||
}
|
||||
void clearAll() {
|
||||
if (!ready()) return;
|
||||
forEachFile([](const char* path, char) { remove(path); });
|
||||
forEachFile([](const char* path, char) {
|
||||
remove(path);
|
||||
char bad[72]; // a set-aside copy (see append()) goes with it: append() always recreates the .bin
|
||||
snprintf(bad, sizeof(bad), "%s.bad", path);
|
||||
remove(bad);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -241,7 +246,15 @@ private:
|
||||
f = fopen(path, "r+b");
|
||||
}
|
||||
if (!f || !readHdr<E>(f, h)) { // new (or unreadable: start it again)
|
||||
if (f) fclose(f);
|
||||
if (f) {
|
||||
// Unreadable (a damaged header, a card edited elsewhere): set it aside
|
||||
// as .bad -- one copy, the newest -- instead of writing over the history.
|
||||
fclose(f);
|
||||
char bad[72];
|
||||
snprintf(bad, sizeof(bad), "%s.bad", path);
|
||||
remove(bad);
|
||||
rename(path, bad);
|
||||
}
|
||||
f = fopen(path, "w+b");
|
||||
if (!f) return;
|
||||
h = { MAGIC, VERSION, (uint16_t)sizeof(E), _keep, 0, 0, 1 };
|
||||
|
||||
@@ -993,7 +993,10 @@ void UITask::navToolsPopup() {
|
||||
_nav_share_lbl = noteLabel(list, "", THEME_FONT_SMALL, theme::TEXT);
|
||||
// Target: channels (as named -- "#" marks a hashtag channel), then
|
||||
// favourite contacts (starred, so the two stay apart).
|
||||
char opts[MAX_GROUP_CHANNELS * 24 + 16 * 40];
|
||||
// Worst case: "\n" + a 31-byte name per channel, "\n" + star (3) + space +
|
||||
// 31 bytes per favourite. Static: ~1.9 KB is a lot for the loop's stack, and
|
||||
// the dropdown copies it.
|
||||
static char opts[MAX_GROUP_CHANNELS * 32 + 16 * 36 + 1];
|
||||
int o = 0, sel = 0;
|
||||
navmap::s_share_n = 0;
|
||||
for (int i = 0; i < MAX_GROUP_CHANNELS && navmap::s_share_n < navmap::SHARE_TARGETS; i++) {
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
Pack& p = _p[i];
|
||||
uint32_t off, len;
|
||||
if (!lookup(p, key, off, len)) continue;
|
||||
if ((uint64_t)p.data_off + off + len > p.size) return false; // an entry pointing past the file
|
||||
FILE* f = handle(i);
|
||||
if (!f || fseek(f, p.data_off + off, SEEK_SET) != 0) return false;
|
||||
s.f = f; s.len = len; s.owned = false;
|
||||
@@ -128,8 +129,10 @@ private:
|
||||
fseek(f, 0, SEEK_END);
|
||||
p.size = (uint32_t)ftell(f);
|
||||
p.index = nullptr;
|
||||
uint32_t isz = p.count * 16;
|
||||
ok = p.index_off + isz <= p.size && p.data_off <= p.size;
|
||||
// In 64 bits / by division: a damaged count would otherwise wrap count * 16
|
||||
// to a small size, pass, and send the index search far past its buffer.
|
||||
ok = p.count <= p.size / 16 && (uint64_t)p.index_off + (uint64_t)p.count * 16 <= p.size && p.data_off <= p.size;
|
||||
uint32_t isz = ok ? p.count * 16 : 0;
|
||||
if (ok && isz <= INDEX_IN_RAM_MAX) {
|
||||
p.index = psramBuf<uint8_t>(isz ? isz : 1);
|
||||
if (p.index && (fseek(f, p.index_off, SEEK_SET) != 0 || !readFast(f, p.index, isz))) { free(p.index); p.index = nullptr; }
|
||||
|
||||
Reference in New Issue
Block a user