Fix #1802 (uninitialised memory read as debugger command history) and clean up a little

This commit is contained in:
Vas Crabb 2016-12-17 08:11:30 +11:00
parent c9fb53a812
commit 44eb44996a
2 changed files with 63 additions and 52 deletions

View File

@ -16,9 +16,15 @@
#include "winutil.h"
// edit box styles
#define EDIT_BOX_STYLE WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL
#define EDIT_BOX_STYLE_EX 0
namespace {
constexpr DWORD EDIT_BOX_STYLE = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
constexpr DWORD EDIT_BOX_STYLE_EX = 0;
constexpr int MAX_EDIT_STRING = 256;
constexpr int HISTORY_LENGTH = 20;
} // anonymous namespace
editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_console, LPCSTR title, WNDPROC handler) :
@ -26,7 +32,7 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co
m_editwnd(nullptr),
m_edit_defstr(),
m_original_editproc(nullptr),
m_history_count(0),
m_history(),
m_last_history(0)
{
if (window() == nullptr)
@ -35,11 +41,11 @@ editwin_info::editwin_info(debugger_windows_interface &debugger, bool is_main_co
// create an edit box and override its key handling
m_editwnd = CreateWindowEx(EDIT_BOX_STYLE_EX, TEXT("EDIT"), nullptr, EDIT_BOX_STYLE,
0, 0, 100, 100, window(), nullptr, GetModuleHandleUni(), nullptr);
m_original_editproc = (WNDPROC)(uintptr_t)GetWindowLongPtr(m_editwnd, GWLP_WNDPROC);
SetWindowLongPtr(m_editwnd, GWLP_USERDATA, (LONG_PTR)this);
SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, (LONG_PTR)&editwin_info::static_edit_proc);
SendMessage(m_editwnd, WM_SETFONT, (WPARAM)metrics().debug_font(), (LPARAM)FALSE);
SendMessage(m_editwnd, EM_LIMITTEXT, (WPARAM)MAX_EDIT_STRING, (LPARAM)0);
m_original_editproc = WNDPROC(uintptr_t(GetWindowLongPtr(m_editwnd, GWLP_WNDPROC)));
SetWindowLongPtr(m_editwnd, GWLP_USERDATA, LONG_PTR(this));
SetWindowLongPtr(m_editwnd, GWLP_WNDPROC, LONG_PTR(&editwin_info::static_edit_proc));
SendMessage(m_editwnd, WM_SETFONT, WPARAM(metrics().debug_font()), LPARAM(FALSE));
SendMessage(m_editwnd, EM_LIMITTEXT, WPARAM(MAX_EDIT_STRING), LPARAM(0));
set_editwnd_text("");
}
@ -80,13 +86,13 @@ void editwin_info::set_editwnd_bounds(RECT const &bounds)
void editwin_info::set_editwnd_text(char const *text)
{
auto tc_buffer = osd::text::to_tstring(text);
SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)tc_buffer.c_str());
SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(tc_buffer.c_str()));
}
void editwin_info::editwnd_select_all()
{
SendMessage(m_editwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
SendMessage(m_editwnd, EM_SETSEL, WPARAM(0), LPARAM(-1));
}
@ -100,8 +106,6 @@ void editwin_info::draw_contents(HDC dc)
LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
{
TCHAR buffer[MAX_EDIT_STRING];
// handle a few messages
switch (message)
{
@ -114,23 +118,28 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
switch (wparam)
{
case VK_UP:
if (m_last_history < (m_history_count - 1))
if (!m_history.empty())
{
m_last_history++;
else
m_last_history = 0;
SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
if (m_last_history >= m_history.size())
m_last_history = 0;
auto const &entry(m_history[m_last_history]);
SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(entry.c_str()));
SendMessage(m_editwnd, EM_SETSEL, WPARAM(entry.length()), LPARAM(entry.length()));
}
break;
case VK_DOWN:
if (m_last_history > 0)
m_last_history--;
else if (m_history_count > 0)
m_last_history = m_history_count - 1;
else
m_last_history = 0;
SendMessage(m_editwnd, WM_SETTEXT, (WPARAM)0, (LPARAM)&m_history[m_last_history][0]);
SendMessage(m_editwnd, EM_SETSEL, (WPARAM)MAX_EDIT_STRING, (LPARAM)MAX_EDIT_STRING);
if (!m_history.empty())
{
if (m_last_history > 0)
m_last_history--;
else
m_last_history = m_history.size() - 1;
auto const &entry(m_history[m_last_history]);
SendMessage(m_editwnd, WM_SETTEXT, WPARAM(0), LPARAM(entry.c_str()));
SendMessage(m_editwnd, EM_SETSEL, WPARAM(entry.length()), LPARAM(entry.length()));
}
break;
case VK_PRIOR:
@ -168,35 +177,36 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
{
if (waiting_for_debugger() || !seq_pressed())
{
TCHAR buffer[MAX_EDIT_STRING];
switch (wparam)
{
case 13:
case 13: // carriage return
{
// fetch the text
SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)ARRAY_LENGTH(buffer), (LPARAM)buffer);
SendMessage(m_editwnd, WM_GETTEXT, WPARAM(ARRAY_LENGTH(buffer)), LPARAM(buffer));
// add to the history if it's not a repeat of the last one
if (buffer[0] != 0 && _tcscmp(buffer, &m_history[0][0]))
if (buffer[0] && (m_history.empty() || _tcscmp(buffer, m_history[0].c_str())))
{
memmove(&m_history[1][0], &m_history[0][0], (HISTORY_LENGTH - 1) * MAX_EDIT_STRING * sizeof(TCHAR));
_tcscpy(&m_history[0][0], buffer);
if (m_history_count < HISTORY_LENGTH)
m_history_count++;
while (m_history.size() >= HISTORY_LENGTH)
m_history.pop_back();
m_history.emplace_front(buffer);
}
m_last_history = m_history_count - 1;
m_last_history = m_history.size() - 1;
// process
{
auto utf8_buffer = osd::text::from_tstring(buffer);
process_string(utf8_buffer.c_str());
}
break;
}
break;
case 27:
case 27: // escape
{
// fetch the text
SendMessage(m_editwnd, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer);
SendMessage(m_editwnd, WM_GETTEXT, WPARAM(sizeof(buffer)), LPARAM(buffer));
// if it's not empty, clear the text
if (_tcslen(buffer) > 0)
@ -205,8 +215,8 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
set_editwnd_text(m_edit_defstr.c_str());
editwnd_select_all();
}
break;
}
break;
default:
return CallWindowProc(m_original_editproc, m_editwnd, message, wparam, lparam);
@ -226,7 +236,7 @@ LRESULT editwin_info::edit_proc(UINT message, WPARAM wparam, LPARAM lparam)
LRESULT CALLBACK editwin_info::static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
{
editwin_info *const info = (editwin_info *)(uintptr_t)GetWindowLongPtr(wnd, GWLP_USERDATA);
editwin_info *const info = (editwin_info *)uintptr_t(GetWindowLongPtr(wnd, GWLP_USERDATA));
assert(info->m_editwnd == wnd);
return info->edit_proc(message, wparam, lparam);
}

View File

@ -6,13 +6,16 @@
//
//============================================================
#ifndef __DEBUG_WIN_EDIT_WIN_INFO_H__
#define __DEBUG_WIN_EDIT_WIN_INFO_H__
#ifndef MAME_DEBUG_WIN_EDIT_WIN_INFO_H
#define MAME_DEBUG_WIN_EDIT_WIN_INFO_H
#include "debugwin.h"
#include "debugwininfo.h"
#include <deque>
#include <string>
class editwin_info : public debugwin_info
{
@ -25,8 +28,8 @@ public:
virtual bool set_default_focus() override;
protected:
static DWORD const COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
static DWORD const COMBO_BOX_STYLE_EX = 0;
constexpr static DWORD COMBO_BOX_STYLE = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL;
constexpr static DWORD COMBO_BOX_STYLE_EX = 0;
void set_editwnd_bounds(RECT const &bounds);
void set_editwnd_text(char const *text);
@ -36,21 +39,19 @@ protected:
virtual void draw_contents(HDC dc) override;
private:
typedef std::deque<std::basic_string<TCHAR> > history_deque;
virtual void process_string(char const *string) = 0;
LRESULT edit_proc(UINT message, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK static_edit_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
static int const MAX_EDIT_STRING = 256;
static int const HISTORY_LENGTH = 20;
HWND m_editwnd;
std::string m_edit_defstr;
WNDPROC m_original_editproc;
TCHAR m_history[HISTORY_LENGTH][MAX_EDIT_STRING];
int m_history_count;
int m_last_history;
HWND m_editwnd;
std::string m_edit_defstr;
WNDPROC m_original_editproc;
history_deque m_history;
int m_last_history;
};
#endif