Debugger: replace sprintf() part 6 - Debugger_Disassembler (PR #1092)

- Improve FormatCharCopy() to not buffer overflow
- Improve FormatOpcodeBytes() to not buffer overflow
- Improve FormatNopcodeBytes() to not buffer overflow
- Change FormatDisassemblyLine() to return std::string
This commit is contained in:
Kelvin Lee 2022-05-01 23:24:35 +10:00 committed by GitHub
parent b9308b36ea
commit 47ba87a015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 115 deletions

View File

@ -7701,8 +7701,8 @@ void OutputTraceLine ()
DisasmLine_t line;
GetDisassemblyLine( regs.pc, line );
char sDisassembly[ CONSOLE_WIDTH ]; // DrawDisassemblyLine( 0,regs.pc, sDisassembly); // Get Disasm String
FormatDisassemblyLine( line, sDisassembly, CONSOLE_WIDTH );
// DrawDisassemblyLine( 0,regs.pc, sDisassembly); // Get Disasm String
std::string sDisassembly = FormatDisassemblyLine( line );
char sFlags[] = "........";
WORD nRegFlags = regs.ps;
@ -7758,9 +7758,9 @@ void OutputTraceLine ()
(unsigned)regs.x,
(unsigned)regs.y,
(unsigned)regs.sp,
(char*) sFlags
, sDisassembly
//, sTarget // TODO: Show target?
sFlags
, sDisassembly.c_str()
//, sTarget.c_str() // TODO: Show target?
);
}
else
@ -7773,9 +7773,9 @@ void OutputTraceLine ()
(unsigned)regs.x,
(unsigned)regs.y,
(unsigned)regs.sp,
(char*) sFlags
, sDisassembly
//, sTarget // TODO: Show target?
sFlags
, sDisassembly.c_str()
//, sTarget.c_str() // TODO: Show target?
);
}
}

View File

@ -27,6 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Memory.h"
inline static void _memsetz(void* dst, int val, size_t len)
{
memset(dst, val, len);
static_cast<char*>(dst)[len] = 0;
}
//===========================================================================
std::string FormatAddress(WORD nAddress, int nBytes)
{
@ -42,9 +48,9 @@ std::string FormatAddress(WORD nAddress, int nBytes)
}
//===========================================================================
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen)
char* FormatCharCopy(char* pDst, const char* pEnd, const char* pSrc, const int nLen)
{
for (int i = 0; i < nLen; i++)
for (int i = 0; i < nLen && pDst < pEnd; i++)
*pDst++ = FormatCharTxtCtrl(*pSrc++);
return pDst;
}
@ -236,22 +242,22 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
nTarget = nBaseAddress + 2 + (int)(signed char)nTarget;
line_.nTarget = nTarget;
sprintf(line_.sTargetValue, "%04X", nTarget & 0xFFFF);
strncpy_s(line_.sTargetValue, WordToHexStr(nTarget & 0xFFFF).c_str(), _TRUNCATE);
// Always show branch indicators
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
if (nTarget < nBaseAddress)
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorUp[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorUp[g_iConfigDisasmBranchType], _TRUNCATE);
else
if (nTarget > nBaseAddress)
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorDown[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorDown[g_iConfigDisasmBranchType], _TRUNCATE);
else
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorEqual[g_iConfigDisasmBranchType]);
strncpy_s(line_.sBranch, g_sConfigBranchIndicatorEqual[g_iConfigDisasmBranchType], _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
sprintf(line_.sTargetPointer, "%04X", nTarget & 0xFFFF);
strncpy_s(line_.sTargetPointer, WordToHexStr(nTarget & 0xFFFF).c_str(), _TRUNCATE);
}
// intentional re-test AM_R ...
@ -326,11 +332,11 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
pTarget = &sAddressBuf;
}
//sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
//sTarget = StrFormat( g_aOpmodes[ iOpmode ].m_sFormat, pTarget->c_str() );
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
{
int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : -line_.nTargetOffset;
sprintf(line_.sTargetOffset, "%d", nAbsTargetOffset);
strncpy_s(line_.sTargetOffset, StrFormat("%d", nAbsTargetOffset).c_str(), _TRUNCATE);
}
strncpy_s(line_.sTarget, pTarget->c_str(), _TRUNCATE);
@ -349,71 +355,72 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
//if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
// sTargetValue_ = WordToHexStr( nTargetValue ); // & 0xFFFF
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
sprintf(line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF);
strncpy_s(line_.sTargetPointer, WordToHexStr(nTargetPointer & 0xFFFF).c_str(), _TRUNCATE);
if (iOpcode != OPCODE_JMP_NA && iOpcode != OPCODE_JMP_IAX)
{
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
sprintf(line_.sTargetValue, "%02X", nTargetValue & 0xFF);
strncpy_s(line_.sTargetValue, ByteToHexStr(nTargetValue & 0xFF).c_str(), _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
line_.nImmediate = (BYTE)nTargetValue;
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
sprintf(line_.sImmediate, "%c", _char);
const char _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
_memsetz(line_.sImmediate, _char, 1);
//if (ConsoleColorIsEscapeMeta( nImmediate_ ))
#if OLD_CONSOLE_COLOR
if (ConsoleColorIsEscapeMeta(_char))
sprintf(line_.sImmediate, "%c%c", _char, _char);
_memsetz(line_.sImmediate, _char, 2);
else
sprintf(line_.sImmediate, "%c", _char);
_memsetz(line_.sImmediate, _char, 1);
#endif
}
//if (iOpmode == AM_NA ) // Indirect Absolute
// sprintf( sTargetValue_, "%04X", nTargetPointer & 0xFFFF );
// sTargetValue_ = WordToHexStr( nTargetPointer & 0xFFFF );
//else
// //sprintf( sTargetValue_, "%02X", nTargetValue & 0xFF );
// sprintf( sTargetValue_, "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
// //sTargetValue_ = ByteToHexStr( nTargetValue & 0xFF );
// sTargetValue_ = StrFormat( "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
}
}
else
{
if (iOpmode == AM_M)
{
//sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, (unsigned)nTarget );
sprintf(line_.sTarget , "%02X", (unsigned)nTarget);
//sTarget = StrFormat( g_aOpmodes[ iOpmode ].m_sFormat, (unsigned)nTarget );
strncpy_s(line_.sTarget, ByteToHexStr(nTarget).c_str(), _TRUNCATE);
if (nTarget == 0)
line_.sImmediateSignedDec[0] = 0; // nothing
else
if (nTarget < 128)
sprintf(line_.sImmediateSignedDec, "+%d" , nTarget );
strncpy_s(line_.sImmediateSignedDec, StrFormat("+%d", nTarget).c_str(), _TRUNCATE);
else
if (nTarget >= 128)
sprintf(line_.sImmediateSignedDec, "-%d" , (~nTarget + 1) & 0xFF );
strncpy_s(line_.sImmediateSignedDec, StrFormat("-%d" , (~nTarget + 1) & 0xFF).c_str(), _TRUNCATE);
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
line_.nImmediate = (BYTE)nTarget;
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
sprintf(line_.sImmediate, "%c", _char);
const char _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
_memsetz(line_.sImmediate, _char, 1);
#if OLD_CONSOLE_COLOR
if (ConsoleColorIsEscapeMeta(_char))
sprintf(line_.sImmediate, "%c%c", _char, _char);
_memsetz(line_.sImmediate, _char, 2);
else
sprintf(line_.sImmediate, "%c", _char);
_memsetz(line_.sImmediate, _char, 1);
#endif
}
}
}
sprintf(line_.sAddress, "%04X", nBaseAddress);
strncpy_s(line_.sAddress, WordToHexStr(nBaseAddress).c_str(), _TRUNCATE);
// Opcode Bytes
FormatOpcodeBytes(nBaseAddress, line_);
@ -431,11 +438,11 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
strcpy(line_.sMnemonic, g_aOpcodes[line_.iOpcode].sMnemonic);
}
int nSpaces = strlen(line_.sOpCodes);
while (nSpaces < (int)nMinBytesLen)
const size_t nOpCodesLen = strlen(line_.sOpCodes);
if (nOpCodesLen < nMinBytesLen)
{
strcat(line_.sOpCodes, " ");
nSpaces++;
memset(line_.sOpCodes + nOpCodesLen, ' ', nMinBytesLen - nOpCodesLen);
line_.sOpCodes[nMinBytesLen] = '\0';
}
return bDisasmFormatFlags;
@ -444,26 +451,25 @@ int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
//===========================================================================
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
{
int nOpbyte = line_.nOpbyte;
char* pDst = line_.sOpCodes;
int nMaxOpBytes = nOpbyte;
if (nMaxOpBytes > DISASM_DISPLAY_MAX_OPCODES) // 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
nMaxOpBytes = DISASM_DISPLAY_MAX_OPCODES;
// 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
const int nMaxOpBytes = min(line_.nOpbyte, DISASM_DISPLAY_MAX_OPCODES);
char* cp = line_.sOpCodes;
const char* const ep = cp + sizeof(line_.sOpCodes);
for (int iByte = 0; iByte < nMaxOpBytes; iByte++)
{
BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
sprintf(pDst, "%02X", nMem); // sBytes+strlen(sBytes)
pDst += 2;
const BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
if ((cp+2) < ep)
cp = StrBufferAppendByteAsHex(cp, nMem);
// TODO: If Disassembly_IsDataAddress() don't show spaces...
if (g_bConfigDisasmOpcodeSpaces)
{
strcat(pDst, " ");
pDst++; // 2.5.3.3 fix
if ((cp+1) < ep)
*cp++ = ' ';
}
}
*cp = '\0';
}
struct FAC_t
@ -509,13 +515,12 @@ void FAC_Unpack(WORD nAddress, FAC_t& fac_)
//===========================================================================
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
{
// TODO: One day, line_.sTarget should become a std::string and things would be much simpler.
char* pDst = line_.sTarget;
const char* pSrc = 0;
DWORD nStartAddress = line_.pDisasmData->nStartAddress;
DWORD nEndAddress = line_.pDisasmData->nEndAddress;
// int nDataLen = nEndAddress - nStartAddress + 1 ;
int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
int len = nDisplayLen;
const char* const pEnd = pDst + sizeof(line_.sTarget);
const DWORD nStartAddress = line_.pDisasmData->nStartAddress;
const DWORD nEndAddress = line_.pDisasmData->nEndAddress;
const int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
for (int iByte = 0; iByte < line_.nOpbyte; )
{
@ -528,14 +533,18 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
case NOP_BYTE_2:
case NOP_BYTE_4:
case NOP_BYTE_8:
sprintf(pDst, "%02X", nTarget8); // sBytes+strlen(sBytes)
pDst += 2;
if ((pDst + 2) < pEnd)
pDst = StrBufferAppendByteAsHex(pDst, nTarget8);
iByte++;
if (line_.iNoptype == NOP_BYTE_1)
{
if (iByte < line_.nOpbyte)
{
if ((pDst + 1) < pEnd)
*pDst++ = ',';
}
}
*pDst = '\0';
break;
case NOP_FAC:
@ -544,27 +553,38 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
FAC_Unpack( nBaseAddress, fac );
const char aSign[2] = { '+', '-' };
if (fac.isZero)
sprintf( pDst, "0" );
{
if ((pDst + 1) < pEnd)
*pDst++ = '0';
}
else
{
double f = fac.mantissa * pow( 2.0, fac.exponent - 32 );
//sprintf( "s%1X m%04X e%02X", fac.negative, fac.mantissa, fac.exponent );
sprintf( pDst, "%c%f", aSign[ fac.negative ], f );
const double f = fac.mantissa * pow( 2.0, fac.exponent - 32 );
//std::string sFac = StrFormat( "s%1X m%04X e%02X", fac.negative, fac.mantissa, fac.exponent );
std::string sFac = StrFormat( "%c%f", aSign[ fac.negative ], f );
if ((pDst + sFac.length()) < pEnd)
{
memcpy(pDst, sFac.c_str(), sFac.length());
pDst += sFac.length();
}
}
iByte += 5;
*pDst = '\0';
break;
}
case NOP_WORD_1:
case NOP_WORD_2:
case NOP_WORD_4:
sprintf(pDst, "%04X", nTarget16); // sBytes+strlen(sBytes)
pDst += 4;
if ((pDst + 4) < pEnd)
pDst = StrBufferAppendWordAsHex(pDst, nTarget16);
iByte += 2;
if (iByte < line_.nOpbyte)
{
if ((pDst + 1) < pEnd)
*pDst++ = ',';
}
*pDst = '\0';
break;
case NOP_ADDRESS:
@ -574,120 +594,124 @@ void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
case NOP_STRING_APPLESOFT:
iByte = line_.nOpbyte;
strncpy(pDst, (const char*)(mem + nBaseAddress), iByte);
if ((pDst + iByte) < pEnd)
{
memcpy(pDst, mem + nBaseAddress, iByte);
pDst += iByte;
}
*pDst = 0;
break;
case NOP_STRING_APPLE:
iByte = line_.nOpbyte; // handle all bytes of text
pSrc = (const char*)mem + nStartAddress;
if (len > (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
{
if (len > DISASM_DISPLAY_MAX_IMMEDIATE_LEN) // no; need extra characters for ellipsis?
len = (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 3); // ellipsis = true
iByte = line_.nOpbyte; // handle all bytes of text
const char* pSrc = (const char*)mem + nStartAddress;
if (nDisplayLen > (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
{
const bool ellipsis = (nDisplayLen > DISASM_DISPLAY_MAX_IMMEDIATE_LEN);
const int len = (ellipsis) ? (DISASM_DISPLAY_MAX_IMMEDIATE_LEN - 3)
: nDisplayLen // no need of extra characters for ellipsis
;
// DISPLAY: text_longer_18...
FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
pDst = FormatCharCopy(pDst, pEnd, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
if (nDisplayLen > len) // ellipsis
if (ellipsis && (pDst + 3) < pEnd)
{
*pDst++ = '.';
*pDst++ = '.';
*pDst++ = '.';
}
}
else { // DISPLAY: "max_18_char"
else
{ // DISPLAY: "max_18_char"
if ((pDst + 1) < pEnd)
*pDst++ = '"';
pDst = FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
pDst = FormatCharCopy(pDst, pEnd, pSrc, nDisplayLen); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
if ((pDst + 1) < pEnd)
*pDst++ = '"';
}
*pDst = 0;
break;
}
default:
#if _DEBUG // Unhandled data disassembly!
int* FATAL = 0;
*FATAL = 0xDEADC0DE;
assert(false);
#endif
iByte++;
break;
}
}
} // switch.
} // for.
}
//===========================================================================
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly, const int nBufferSize)
std::string FormatDisassemblyLine(const DisasmLine_t& line)
{
//> Address Separator Opcodes Label Mnemonic Target [Immediate] [Branch]
//
// Data Disassembler
// Label Directive [Immediate]
const char* pMnemonic = g_aOpcodes[line.iOpcode].sMnemonic;
sprintf(sDisassembly, "%s:%s %s "
std::string sDisassembly = StrFormat( "%s:%s %s "
, line.sAddress
, line.sOpCodes
, pMnemonic
, g_aOpcodes[line.iOpcode].sMnemonic
);
/*
if (line.bTargetIndexed || line.bTargetIndirect)
{
strcat( sDisassembly, "(" );
}
sDisassembly += '(';
if (line.bTargetImmediate)
strcat( sDisassembly, "#$" );
sDisassembly += "#$";
if (line.bTargetValue)
strcat( sDisassembly, line.sTarget );
sDisassembly += line.sTarget;
if (line.bTargetIndirect)
{
if (line.bTargetX)
strcat( sDisassembly, ", X" );
sDisassembly += ", X";
if (line.bTargetY)
strcat( sDisassembly, ", Y" );
sDisassembly += ", Y";
}
if (line.bTargetIndexed || line.bTargetIndirect)
{
strcat( sDisassembly, ")" );
}
sDisassembly += ')';
if (line.bTargetIndirect)
{
if (line.bTargetY)
strcat( sDisassembly, ", Y" );
sDisassembly += ", Y";
}
*/
char sTarget[32];
if (line.bTargetValue || line.bTargetRelative || line.bTargetImmediate)
{
if (line.bTargetRelative)
{
strcpy(sTarget, line.sTargetValue);
sDisassembly += '$';
sDisassembly += line.sTargetValue;
}
else
{
if (line.bTargetImmediate)
{
strcat(sDisassembly, "#");
strncpy(sTarget, line.sTarget, sizeof(sTarget));
sTarget[sizeof(sTarget) - 1] = 0;
sDisassembly += "#$";
sDisassembly += line.sTarget;
}
else
sprintf(sTarget, g_aOpmodes[line.iOpmode].m_sFormat, line.nTarget);
{
sDisassembly += '$';
sDisassembly += StrFormat( g_aOpmodes[line.iOpmode].m_sFormat, line.nTarget );
}
}
}
strcat(sDisassembly, "$");
strcat(sDisassembly, sTarget);
}
return sDisassembly;
}
// Given an Address, and Line to display it on

View File

@ -1,16 +1,12 @@
#pragma once
int GetDisassemblyLine(const WORD nOffset, DisasmLine_t& line_);
// , int iOpcode, int iOpmode, int nOpbytes
// char *sAddress_, char *sOpCodes_,
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char *sTargetValue_,
// char * sImmediate_, char & nImmediate_, char *sBranch_ );
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly_, const int nBufferSize);
std::string FormatDisassemblyLine(const DisasmLine_t& line);
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
std::string FormatAddress(WORD nAddress, int nBytes);
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen);
char* FormatCharCopy(char* pDst, const char* pEnd, const char* pSrc, const int nLen);
char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_ = NULL);
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_ = NULL);