Skip to content

Commit f0f25b6

Browse files
committed
[debugger] Validate debug settings before loading
1 parent 148d56b commit f0f25b6

3 files changed

Lines changed: 247 additions & 47 deletions

File tree

platforms/shared/desktop/gui_debug.cpp

Lines changed: 128 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
#include "emu.h"
4141
#include "config.h"
4242

43+
static const char* GLDEBUG_MAGIC = "GLDEBUG2";
44+
static const int GLDEBUG_MAGIC_LEN = 8;
45+
static const int GLDEBUG_MAX_RECORDS = 0x10000;
46+
47+
static bool read_settings_data(std::istream& stream, void* data, size_t size);
48+
static bool read_settings_bool(std::istream& stream, bool& value);
49+
static bool read_settings_count(std::istream& stream, int& count, size_t record_size);
50+
4351
void gui_debug_init(void)
4452
{
4553
gui_debug_trace_logger_init();
@@ -131,9 +139,6 @@ void gui_debug_windows(void)
131139
}
132140
}
133141

134-
static const char* GLDEBUG_MAGIC = "GLDEBUG2";
135-
static const int GLDEBUG_MAGIC_LEN = 8;
136-
137142
void gui_debug_save_settings(const char* file_path)
138143
{
139144
std::ofstream file(file_path, std::ios::binary);
@@ -196,49 +201,93 @@ void gui_debug_load_settings(const char* file_path)
196201
}
197202

198203
char magic[8] = {};
199-
file.read(magic, GLDEBUG_MAGIC_LEN);
200-
if (file.gcount() != GLDEBUG_MAGIC_LEN || memcmp(magic, GLDEBUG_MAGIC, GLDEBUG_MAGIC_LEN) != 0)
204+
if (!read_settings_data(file, magic, GLDEBUG_MAGIC_LEN) ||
205+
memcmp(magic, GLDEBUG_MAGIC, GLDEBUG_MAGIC_LEN) != 0)
201206
{
202207
Log("Invalid debug settings file: %s", file_path);
203-
file.close();
204208
return;
205209
}
206210

207211
GearlynxCore* core = emu_get_core();
208212
M6502* processor = core->GetM6502();
209213

210-
processor->ResetBreakpoints();
214+
M6502::GLYNX_Breakpoint breakpoint = {};
215+
size_t breakpoint_size = sizeof(breakpoint.enabled) + sizeof(breakpoint.address1) +
216+
sizeof(breakpoint.address2) + sizeof(breakpoint.read) + sizeof(breakpoint.write) +
217+
sizeof(breakpoint.execute) + sizeof(breakpoint.range);
211218
int bp_count = 0;
212-
file.read((char*)&bp_count, sizeof(int));
213-
std::vector<M6502::GLYNX_Breakpoint>* breakpoints = processor->GetBreakpoints();
219+
if (!read_settings_count(file, bp_count, breakpoint_size))
220+
{
221+
Log("Invalid debug settings file: %s", file_path);
222+
return;
223+
}
224+
225+
std::vector<M6502::GLYNX_Breakpoint> breakpoints;
226+
breakpoints.reserve((size_t)bp_count);
214227
for (int i = 0; i < bp_count; i++)
215228
{
216-
M6502::GLYNX_Breakpoint bp;
217-
file.read((char*)&bp.enabled, sizeof(bool));
218-
file.read((char*)&bp.address1, sizeof(u16));
219-
file.read((char*)&bp.address2, sizeof(u16));
220-
file.read((char*)&bp.read, sizeof(bool));
221-
file.read((char*)&bp.write, sizeof(bool));
222-
file.read((char*)&bp.execute, sizeof(bool));
223-
file.read((char*)&bp.range, sizeof(bool));
224-
breakpoints->push_back(bp);
229+
M6502::GLYNX_Breakpoint bp = {};
230+
if (!read_settings_bool(file, bp.enabled) ||
231+
!read_settings_data(file, &bp.address1, sizeof(bp.address1)) ||
232+
!read_settings_data(file, &bp.address2, sizeof(bp.address2)) ||
233+
!read_settings_bool(file, bp.read) ||
234+
!read_settings_bool(file, bp.write) ||
235+
!read_settings_bool(file, bp.execute) ||
236+
!read_settings_bool(file, bp.range))
237+
{
238+
Log("Invalid debug settings file: %s", file_path);
239+
return;
240+
}
241+
breakpoints.push_back(bp);
225242
}
226243

227-
file.read((char*)emu_debug_irq_breakpoints, sizeof(bool) * 8);
244+
bool irq_breakpoints[8] = {};
245+
for (int i = 0; i < 8; i++)
246+
{
247+
if (!read_settings_bool(file, irq_breakpoints[i]))
248+
{
249+
Log("Invalid debug settings file: %s", file_path);
250+
return;
251+
}
252+
}
228253

229-
gui_debug_reset_disassembler_bookmarks();
254+
struct DasmBookmark { u16 address; char name[32]; };
255+
DasmBookmark bookmark = {};
256+
size_t bookmark_size = sizeof(bookmark.address) + sizeof(bookmark.name);
230257
int bookmark_count = 0;
231-
file.read((char*)&bookmark_count, sizeof(int));
258+
if (!read_settings_count(file, bookmark_count, bookmark_size))
259+
{
260+
Log("Invalid debug settings file: %s", file_path);
261+
return;
262+
}
263+
264+
std::vector<DasmBookmark> bookmarks;
265+
bookmarks.reserve((size_t)bookmark_count);
232266
for (int i = 0; i < bookmark_count; i++)
233267
{
234-
u16 address;
235-
char name[32];
236-
file.read((char*)&address, sizeof(u16));
237-
file.read(name, 32);
238-
gui_debug_add_disassembler_bookmark(address, name);
268+
DasmBookmark item = {};
269+
if (!read_settings_data(file, &item.address, sizeof(item.address)) ||
270+
!read_settings_data(file, item.name, sizeof(item.name)))
271+
{
272+
Log("Invalid debug settings file: %s", file_path);
273+
return;
274+
}
275+
item.name[sizeof(item.name) - 1] = 0;
276+
bookmarks.push_back(item);
277+
}
278+
279+
if (!gui_debug_memory_load_settings(file))
280+
{
281+
Log("Invalid debug settings file: %s", file_path);
282+
return;
239283
}
240284

241-
gui_debug_memory_load_settings(file);
285+
processor->GetBreakpoints()->swap(breakpoints);
286+
memcpy(emu_debug_irq_breakpoints, irq_breakpoints, sizeof(irq_breakpoints));
287+
288+
gui_debug_reset_disassembler_bookmarks();
289+
for (int i = 0; i < bookmark_count; i++)
290+
gui_debug_add_disassembler_bookmark(bookmarks[i].address, bookmarks[i].name);
242291

243292
file.close();
244293

@@ -290,3 +339,55 @@ void gui_debug_auto_load_settings(void)
290339

291340
gui_debug_load_settings(path.c_str());
292341
}
342+
343+
static bool read_settings_data(std::istream& stream, void* data, size_t size)
344+
{
345+
stream.read((char*)data, (std::streamsize)size);
346+
return !stream.fail() && stream.gcount() == (std::streamsize)size;
347+
}
348+
349+
static bool read_settings_bool(std::istream& stream, bool& value)
350+
{
351+
u8 data[sizeof(bool)] = {};
352+
bool false_value = false;
353+
bool true_value = true;
354+
355+
if (!read_settings_data(stream, data, sizeof(data)))
356+
return false;
357+
if (memcmp(data, &false_value, sizeof(data)) == 0)
358+
{
359+
value = false;
360+
return true;
361+
}
362+
if (memcmp(data, &true_value, sizeof(data)) == 0)
363+
{
364+
value = true;
365+
return true;
366+
}
367+
368+
return false;
369+
}
370+
371+
static bool read_settings_count(std::istream& stream, int& count, size_t record_size)
372+
{
373+
if (!read_settings_data(stream, &count, sizeof(count)))
374+
return false;
375+
if (count < 0 || count > GLDEBUG_MAX_RECORDS || record_size == 0)
376+
return false;
377+
378+
std::streampos position = stream.tellg();
379+
if (position == std::streampos(-1))
380+
return false;
381+
382+
stream.seekg(0, std::ios::end);
383+
std::streampos end = stream.tellg();
384+
if (end == std::streampos(-1))
385+
return false;
386+
387+
stream.seekg(position);
388+
if (stream.fail() || end < position)
389+
return false;
390+
391+
u64 remaining = (u64)(end - position);
392+
return (u64)count <= remaining / record_size;
393+
}

platforms/shared/desktop/gui_debug_memory.cpp

Lines changed: 118 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,16 @@ static MemEditor mem_edit[MEMORY_EDITOR_MAX];
3232
static int mem_edit_select = -1;
3333
static int current_mem_edit = 0;
3434
static char set_value_buffer[5] = {0};
35-
36-
static int memory_editor_cart_bank(int editor)
37-
{
38-
switch (editor)
39-
{
40-
case MEMORY_EDITOR_BANK0:
41-
return Media::CART_BANK_0;
42-
case MEMORY_EDITOR_BANK0A:
43-
return Media::CART_BANK_0_A;
44-
case MEMORY_EDITOR_BANK1:
45-
return Media::CART_BANK_1;
46-
case MEMORY_EDITOR_BANK1A:
47-
return Media::CART_BANK_1_A;
48-
default:
49-
return -1;
50-
}
51-
}
35+
static const int DEBUG_MEMORY_MAX_SETTINGS_RECORDS = 0x10000;
5236

5337
static void memory_editor_menu(void);
5438
static void draw_tabs(void);
39+
static bool memory_settings_read_data(std::istream& stream, void* data, size_t size);
40+
static bool memory_settings_read_count(std::istream& stream, int& count, size_t record_size);
41+
static bool memory_settings_read_editor(std::istream& stream, std::vector<MemEditor::Bookmark>& bookmarks,
42+
std::vector<MemEditor::Watch>& watches, u32& total_records);
43+
static int memory_editor_cart_bank(int editor);
44+
5545

5646
void gui_debug_memory_init(void)
5747
{
@@ -588,10 +578,119 @@ void gui_debug_memory_save_settings(std::ostream& stream)
588578
}
589579
}
590580

591-
void gui_debug_memory_load_settings(std::istream& stream)
581+
bool gui_debug_memory_load_settings(std::istream& stream)
592582
{
583+
std::vector<MemEditor::Bookmark> bookmarks[MEMORY_EDITOR_MAX];
584+
std::vector<MemEditor::Watch> watches[MEMORY_EDITOR_MAX];
585+
u32 total_records = 0;
586+
587+
for (int i = 0; i < MEMORY_EDITOR_MAX; i++)
588+
{
589+
if (!memory_settings_read_editor(stream, bookmarks[i], watches[i], total_records))
590+
return false;
591+
}
592+
593593
for (int i = 0; i < MEMORY_EDITOR_MAX; i++)
594594
{
595-
mem_edit[i].LoadSettings(stream);
595+
mem_edit[i].GetBookmarks()->swap(bookmarks[i]);
596+
mem_edit[i].GetWatches()->swap(watches[i]);
597+
}
598+
599+
return true;
600+
}
601+
602+
static bool memory_settings_read_data(std::istream& stream, void* data, size_t size)
603+
{
604+
stream.read((char*)data, (std::streamsize)size);
605+
return !stream.fail() && stream.gcount() == (std::streamsize)size;
606+
}
607+
608+
static bool memory_settings_read_count(std::istream& stream, int& count, size_t record_size)
609+
{
610+
if (!memory_settings_read_data(stream, &count, sizeof(count)))
611+
return false;
612+
if (count < 0 || count > DEBUG_MEMORY_MAX_SETTINGS_RECORDS || record_size == 0)
613+
return false;
614+
615+
std::streampos position = stream.tellg();
616+
if (position == std::streampos(-1))
617+
return false;
618+
619+
stream.seekg(0, std::ios::end);
620+
std::streampos end = stream.tellg();
621+
if (end == std::streampos(-1))
622+
return false;
623+
624+
stream.seekg(position);
625+
if (stream.fail() || end < position)
626+
return false;
627+
628+
u64 remaining = (u64)(end - position);
629+
return (u64)count <= remaining / record_size;
630+
}
631+
632+
static bool memory_settings_read_editor(std::istream& stream, std::vector<MemEditor::Bookmark>& bookmarks,
633+
std::vector<MemEditor::Watch>& watches, u32& total_records)
634+
{
635+
MemEditor::Bookmark bookmark = {};
636+
size_t bookmark_size = sizeof(bookmark.address) + sizeof(bookmark.name);
637+
int bookmark_count = 0;
638+
if (!memory_settings_read_count(stream, bookmark_count, bookmark_size) ||
639+
(u32)bookmark_count > DEBUG_MEMORY_MAX_SETTINGS_RECORDS - total_records)
640+
return false;
641+
642+
total_records += (u32)bookmark_count;
643+
bookmarks.reserve((size_t)bookmark_count);
644+
for (int i = 0; i < bookmark_count; i++)
645+
{
646+
MemEditor::Bookmark item = {};
647+
if (!memory_settings_read_data(stream, &item.address, sizeof(item.address)) ||
648+
!memory_settings_read_data(stream, item.name, sizeof(item.name)))
649+
return false;
650+
651+
item.name[sizeof(item.name) - 1] = 0;
652+
bookmarks.push_back(item);
653+
}
654+
655+
MemEditor::Watch watch = {};
656+
size_t watch_size = sizeof(watch.address) + sizeof(watch.notes) +
657+
sizeof(watch.size) + sizeof(watch.format);
658+
int watch_count = 0;
659+
if (!memory_settings_read_count(stream, watch_count, watch_size) ||
660+
(u32)watch_count > DEBUG_MEMORY_MAX_SETTINGS_RECORDS - total_records)
661+
return false;
662+
663+
total_records += (u32)watch_count;
664+
watches.reserve((size_t)watch_count);
665+
for (int i = 0; i < watch_count; i++)
666+
{
667+
MemEditor::Watch item = {};
668+
if (!memory_settings_read_data(stream, &item.address, sizeof(item.address)) ||
669+
!memory_settings_read_data(stream, item.notes, sizeof(item.notes)) ||
670+
!memory_settings_read_data(stream, &item.size, sizeof(item.size)) ||
671+
!memory_settings_read_data(stream, &item.format, sizeof(item.format)))
672+
return false;
673+
674+
item.notes[sizeof(item.notes) - 1] = 0;
675+
watches.push_back(item);
676+
}
677+
678+
return true;
679+
}
680+
681+
static int memory_editor_cart_bank(int editor)
682+
{
683+
switch (editor)
684+
{
685+
case MEMORY_EDITOR_BANK0:
686+
return Media::CART_BANK_0;
687+
case MEMORY_EDITOR_BANK0A:
688+
return Media::CART_BANK_0_A;
689+
case MEMORY_EDITOR_BANK1:
690+
return Media::CART_BANK_1;
691+
case MEMORY_EDITOR_BANK1A:
692+
return Media::CART_BANK_1_A;
693+
default:
694+
return -1;
596695
}
597696
}

platforms/shared/desktop/gui_debug_memory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ EXTERN void gui_debug_memory_search_capture(int editor);
7373
EXTERN int gui_debug_memory_search(int editor, int op, int compare_type, int compare_value, int data_type, void** results_ptr);
7474
EXTERN int gui_debug_memory_find_bytes(int editor, const char* hex_str, int* out_addresses, int max_results);
7575
EXTERN void gui_debug_memory_save_settings(std::ostream& stream);
76-
EXTERN void gui_debug_memory_load_settings(std::istream& stream);
76+
EXTERN bool gui_debug_memory_load_settings(std::istream& stream);
7777

7878
#undef GUI_DEBUG_MEMORY_IMPORT
7979
#undef EXTERN

0 commit comments

Comments
 (0)